2011-02-24 15 views
0

我正在維護一個用2.3(.5我認爲)編寫的舊rails應用程序。有一個效率低下的選擇導致了我試圖修復的舊N + 1問題。如何使用rails 2.3中的條件重新加載具有熱切負載的集合?

首先,一個Widgets集合在交換機中加載了不同的find_by_sql語句。之後就是做N + 1的Widget.association.select。我想用基於find_by_sql中Widgets的id的Widgets加載替換這個選擇循環。我意識到我可以將它們組合成1個查詢,但find_by_sql相當複雜,所以在這一點上,我正在採取一些小步驟來優化希望的2個查詢。

所以基本上我有

@widgets = Widget.find_by_sql...

,現在我想用@widgets做類似

@widgets_and_more = Widget.find(:all, :include => :widget_assoc, :conditions => ["widgets.id IN ", @widgets.ids]) 

回答

0

你可以使用collectmap獲得ID的數組用於IN...部分的查詢...

@widgets_and_more = Widget.find(:all, :include => :widget_assoc, :conditions => ["widgets.id IN (?)", @widgets.collect(&:id)]) 

或者,因爲Rails會很好地處理它,並在每個對象的調用.to_param,你可以簡單地使用的@widgets數組(這是假設他們是Widget實例,並.to_param迴應顯然)...

@widgets_and_more = Widget.find(:all, :include => :widget_assoc, :conditions => ["widgets.id IN (?)", @widgets]) 

正如你在你的問題中所說的那樣,將兩個查詢結合在一起將是一種更加優雅的處理方式。如果你打算這樣做,你可能需要考慮獲得第一個查詢來選擇id,所以至少你不會在內存中不必要地存儲兩批相同的數據。