2009-03-27 17 views
1

ルビー・オン・レールでは、すべてhas_many :widgetsメソッドはobject.widgetsメソッドとobject.widget_idsメソッドの両方を生成します。名前付きスコープ内の要素のIDを取得する

後者の方法は、ActiveRecordオブジェクトの作成をバイパスし、はるかに高速なクエリを実行するため、非常に便利です。クエリの速度は:selectオプションを使用することで改善できますが、整数ではなくオブジェクトを生成する際にはもっと多くのメモリが割り当てられます。

User has_many :historical_sessions: 

>> Benchmark.measure { User.find(4).historical_sessions.map(&:id) } 
HistoricalSession Load (131.0ms) SELECT * FROM `historical_sessions` WHERE (`historical_sessions`.user_id = 4) 
=> #<Benchmark::Tms:0xbe805c0 @cutime=0.0, @label="", @total=1.996, @stime=0.0150000000000006, @real=2.09599995613098, @utime=1.981, @cstime=0.0> 
(2.1 seconds) 

>> Benchmark.measure { User.find(4).historical_session_ids } 
HistoricalSession Load (34.0ms) SELECT `historical_sessions`.id FROM `historical_sessions` WHERE (`historical_sessions`.user_id = 4) 
=> #<Benchmark::Tms:0x11e6cd94 @cutime=0.0, @label="", @total=1.529, @stime=0.032, @real=1.55099987983704, @utime=1.497, @cstime=0.0> 
(1.6 seconds) 

例えば

(結果セットが67353個のオブジェクトである)

はnamed_scopesを使用した場合と同じ動作が起こる持っているそこの方法ですか?例えば

User named_scope :recent 
User.recent (Exists) 
User.recent_ids (Does not exist) 

私は現在、名前付き範囲の結果セット内のオブジェクトのIDを取得する方法である: HistoricalSession.recent.map(&:ID)。これは基本的に上記の後者の例で行われているのと似ており、明らかに効率的ではありません。私が最後に必要なのは、IDの配列ですが、私はHistoricalSessionオブジェクト全体を構築したくありません。

別の実装では、新しい.findメソッドを使用できます。たとえば、HistoricalSession.recent.find_attributes(:id)です。このメソッドは、selectステートメントを置き換えて指定された値のみを選択し、ActiveRecordオブジェクトの作成を短絡して配列を返します。

提案がありますか?これは簡単なプラグインで書くことができますか?

答えて

2

追加のメソッドを作成する代わりに、「ids」という名前のアソシエーションプロキシでメソッドを作成し、たとえば、この:

User.named_scope :recent, ... 
User.named_scope :admin, ... 
User.recent.admin.ids 

そして、ええ、それは私にとって賢明なプラグインのように聞こえます。書くのは難しくありません。

0

ここで別の見解を取るのはなぜですか?どのくらいのメモリを使用していますか?何かを最適化しようとしているようですが、行数が少なすぎると(つまり数百未満の場合)、なぜこれについて作業を進めているのか分かりません。

問題がありますか、それとも想像していますか?

を忘れないでください:http://en.wikipedia.org/wiki/Program_optimization#When_to_optimize

:-D