2009-03-27 6 views
2

が更新悪いSQLをレンダリング:モデルの関係にRailsはテーブルに参加

を含めるために、私は多くに多くを持っているバンドとイベントの間でテーブルを結合する(イベントが多くのバンドを持って、バンドは多くのイベントがあります...)

私は、すべてのイベントをリストするメインページと、過去7日間に更新されたイベントを表示する最近のページを持っています。最近の方法は、すべての

@events = Event.find(:all, :include => [:venue, :bands], :conditions => {:updated_at => d1..DateTime.now}, :order => 'events.updated_at desc') 

を含まれており、主な方法は、各イベントのためにバンドテーブルを照会恐ろしいSQLを生成ジョインと完璧なSQLを生成し、なぜ

誰かが説明してもらえます。

@events = Event.find(:all, :include => [:venue, :bands], :order => 'events.day') 

どちらも同じビューを使用しているため、他の処理/クエリは実行されません。この2つの唯一の違いは、:conditionsパラメータとそれがソートしている列です。これは私を夢中にさせている!によって生成された

申し訳ありませんが、ここで私のモデルとそれらの関係がある

event.rb

has_many :event_bands 
has_many :bands, :through => :event_bands 
belongs_to :venue 

band.rb

has_many :event_bands 
has_many :events, :through => :event_bands 

event_bands.rb

belongs_to :event 
belongs_to :band 

SQL最近の:

Processing EventlistController#recent (for 127.0.0.1 at 2009-03-27 14:58:10) [GET] 
    [4;35;1mSQL (0.0ms)[0m [0mSET SQL_AUTO_IS_NULL=0[0m 
    [4;36;1mEvent Columns (16.0ms)[0m [0;1mSHOW FIELDS FROM `events`[0m 
    [4;35;1mVenue Columns (15.0ms)[0m [0mSHOW FIELDS FROM `venues`[0m 
    [4;36;1mBand Columns (16.0ms)[0m [0;1mSHOW FIELDS FROM `bands`[0m 
    [4;35;1mEvent Load Including Associations (31.0ms)[0m [0mSELECT `events`.`id` AS t0_r0, `events`.`is_local` AS t0_r1, `events`.`link` AS t0_r2, `events`.`notes` AS t0_r3, `events`.`band_id` AS t0_r4, `events`.`venue_id` AS t0_r5, `events`.`created_at` AS t0_r6, `events`.`updated_at` AS t0_r7, `events`.`day` AS t0_r8, `events`.`band_list` AS t0_r9, `venues`.`id` AS t1_r0, `venues`.`name` AS t1_r1, `venues`.`link` AS t1_r2, `venues`.`map` AS t1_r3, `venues`.`notes` AS t1_r4, `venues`.`created_at` AS t1_r5, `venues`.`updated_at` AS t1_r6, `bands`.`id` AS t2_r0, `bands`.`name` AS t2_r1, `bands`.`link` AS t2_r2, `bands`.`notes` AS t2_r3, `bands`.`is_local` AS t2_r4, `bands`.`created_at` AS t2_r5, `bands`.`updated_at` AS t2_r6 FROM `events` LEFT OUTER JOIN `venues` ON `venues`.id = `events`.venue_id LEFT OUTER JOIN `event_bands` ON (`events`.`id` = `event_bands`.`event_id`) LEFT OUTER JOIN `bands` ON (`bands`.`id` = `event_bands`.`band_id`) WHERE (`events`.`updated_at` BETWEEN '2009-03-20 14:58:10' AND '2009-03-27 14:58:10') 

彼らは二つの異なるSQLクエリを生成する理由はRailsは、デフォルトでは、加入が少ないためにあなたのSQLクエリを最適化しようとするということであるメイン

Processing EventlistController#index (for 127.0.0.1 at 2009-03-27 14:15:47) [GET] 
    [4;35;1mSQL (0.0ms)[0m [0mSET SQL_AUTO_IS_NULL=0[0m 
    [4;36;1mEvent Load (0.0ms)[0m [0;1mSELECT * FROM `events` ORDER BY events.day[0m 
    [4;35;1mEvent Columns (15.0ms)[0m [0mSHOW FIELDS FROM `events`[0m 
    [4;36;1mVenue Columns (16.0ms)[0m [0;1mSHOW FIELDS FROM `venues`[0m 
    [4;35;1mVenue Load (0.0ms)[0m [0mSELECT * FROM `venues` WHERE (`venues`.`id` IN (6,7,8,9,1,2,3,4,5)) [0m 
    [4;36;1mEventBand Load (0.0ms)[0m [0;1mSELECT `event_bands`.* FROM `event_bands` WHERE (`event_bands`.event_id IN (1,24,74,2,75,11,12,3,13,129,76,14,77,78,145,4,146,120,15,130,79,147,5,80,148,144,131,81,132,16,28,82,121,133,83,17,134,84,149,6,18,135,85,122,19,7,136,86,20,9,87,25,137,150,22,138,88,151,124,123,139,89,152,140,90,141,91,8,153,21,142,154,125,143,92,126,10,93,94,155,127,95,128,23,96,97,26,98,99,27,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119)) [0m 
    [4;35;1mEventBand Columns (0.0ms)[0m [0mSHOW FIELDS FROM `event_bands`[0m 
    [4;36;1mBand Columns (16.0ms)[0m [0;1mSHOW FIELDS FROM `bands`[0m 
    [4;35;1mBand Load (0.0ms)[0m [0mSELECT * FROM `bands` WHERE (`bands`.` 
+0

あなたが取り出した最初のSQLは何ですか?条件:それは、それが:条件または:順序によるものかどうかを少なくとも伝えます。 –

+0

さらに、両方の例で生成されたSQLを投稿してください。また、どのレールバージョンを使用しているのですか?これは、最近数ヶ月間に流行してきたエリアです。 – MarkusQ

+0

それは:注文ではない、私はそれを取る場合は、SQLは同じままです。 私はレールを使用しています2.2.2 – Luke

答えて

3

によって生成されたSQL。他のテーブルの使用を必要とする検索の一部として条件のリストを含めると、結果として得られるSQLには結合が含まれている必要があります。しかし、検索しているオブジェクトとの関係をオブジェクトにあらかじめ設定しておけば、Railsは大きな遅いクエリではなく、複数の高速クエリを実行する方が効率的だと考えています。

Railsは、関連するすべてのレコードを1つのクエリでロードしようとするため、N + 1の問題は発生しません。

+0

ありがとう、これは理にかなっています。ですから、ActiveRecordsにそのようなことをさせるのがあなたのお勧めですか? – Luke

+0

おそらく、そうです。随時、必要に応じてカスタムSQLを記述してください。 ActiveRecordは世界のすべての問題を解決することはできません。しかし、この特定のケースでは、実際には、狂気の理由があります。 –

+0

当然。私はこの単純な結合の結果によって本当に混乱しました。 ありがとう! – Luke