2012-03-21 17 views
3

をフェッチする方法を含んで使用する場合、私は、次のモデル構造持って余分なクエリを発射されていますはなぜActive Recordは、私がデータ

class Group < ActiveRecord::Base 
    has_many :group_products, :dependent => :destroy 
    has_many :products, :through => :group_products 
end 

class Product < ActiveRecord::Base 
    has_many :group_products, :dependent => :destroy 
    has_many :groups, :through => :group_products 
end 

class GroupProduct < ActiveRecord::Base 
    belongs_to :group 
    belongs_to :product 
end 

を、私は、コンソールIをincludes.In使用することを決めたので、私は私のデータベースクエリを最小限にしたかったです何かなどを試してみました、

groups = Group.includes(:products) 

私の開発ログは私が

Group Load (403.0ms) SELECT `groups`.* FROM `groups` 
GroupProduct Load (60.0ms) SELECT `group_products`.* FROM `group_products` WHERE (`group_products`.group_id IN (1,3,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,33,42,49,51)) 
Product Load (22.0ms) SELECT `products`.* FROM `products` WHERE (`products`.`id` IN (382,304,353,12,63,103,104,105,262,377,263,264,265,283,284,285,286,287,302,306,307,308,328,335,336,337,340,355,59,60,61,247,309,311,66,30,274,294,324,350,140,176,177,178,64,240,327,332,338,380,383,252,254,255,256,257,325,326)) 
Product Load (10.0ms) SELECT `products`.* FROM `products` WHERE (`products`.`id` = 377) LIMIT 1 

、次の呼び出しを示し、最初の3つのコールが必要であると分析できましたが、最後のデータベースコールが行われた理由はわかりません。何が起こっているのですか? ありがとうございます。 :)

+0

- 記事の下に読む

は熱心なロードを実行するためのさまざまな方法についてより多くのあなたを説明します。 ActiveRecordは、必要なときにのみSQLクエリを起動します。すべてのグループと関連する製品を取得する場合、ARはgroup.productsを呼び出すときにのみ、製品のクエリをトリガーします。 – sailor

答えて

0

私は4番目のクエリがこのコード行(またはそれによって作成されたコレクション)から来ているとは思わない。あなたが後でgroups.products.find(product_id)のようなことを行ったとしても、ジョインテーブルの内側ジョインではるかに複雑なクエリが表示されます。別のProduct.find(product_id)などがコードのどこかに似ている必要があります。

2

where()コールを発行するときに同様の問題が発生していました。この問題は、ActiveRecords::Relation(先ほど述べたセーラーとして)で行われている「怠惰な評価」が原因です。解決策は、通話の最後に.to_aを追加することです。上記のあなたのincludes()ステートメントでも動作するはずです。詳細情報については、以下を参照してください。(。N + 1つのクエリおよび未使用の積極的なロードを殺すためにヘルプ)

http://daveinabottle.schweisguth.org/2011/05/01/avoiding-extra-queries-in-activerecord-3/

0

を今、あなたは簡単にbullet宝石を使用してN + 1クエリの呼び出しを見つけることができます

この宝石、それを使用しますN + 1コールを殺すために回避する必要がある場所を教えてくれます。

これは私がこれをたくさん使うのを助け、それを試してみると、あなたの問題の解決を得るでしょう。私はそれが遅延ロードが原因だと思う

3 ways to do eager loading (preloading) in Rails 3 & 4

関連する問題