これは、「これをどうやって行うのか分からない」という質問ではなく、「なぜ物事はこのように動作するのか」という質問です...
したがって、使用する予定の関連レコードを取得する際の絶対的な方法は、:include
結合が行われ、大量の追加クエリを回避できるため、 を使用することです。
Post.all(:include => :comments)
しかし、ログを見ると、結合は行われていません。
Post Load (3.7ms) SELECT * FROM "posts"
Comment Load (0.2ms) SELECT "comments.*" FROM "comments"
WHERE ("comments".post_id IN (1,2,3,4))
ORDER BY created_at asc)
これはすべてのコメントを一度に取得するためショートカットになりますが、それでも結合ではありません (すべてのドキュメントでそう書かれているようです)。結合できる唯一の方法は、:joins
の代わりにを使用することです:include
。
Post.all(:joins => :comments)
ログには次のように表示されます:
Post Load (6.0ms) SELECT "posts".* FROM "posts"
INNER JOIN "comments" ON "posts".id = "comments".post_id
何か見落としているのでしょうか? 6 つの関連付けを持つアプリがあり、1 つの画面にそれらすべてのデータを表示しています。6 つの個別のクエリではなく、結合された 1 つのクエリを使用する方がよいようです。パフォーマンスの点では、個別のクエリよりも結合を実行する方が常に優れているわけではないことはわかっています (実際、費やした時間で判断すると、上記の 2 つの個別のクエリの方が結合よりも高速であるように見えます)。しかし、私が読んだすべてのドキュメントの後、:include
宣伝どおりに動作しないことに驚いています。
Rails はパフォーマンスの問題を認識しており、特定の場合を除いて結合しないのでしょうか?
ベストアンサー1
Rails 2.1 で機能が変更されたようです:include
。Rails は以前はすべてのケースで結合を実行していましたが、パフォーマンス上の理由から、状況によっては複数のクエリを使用するように変更されました。このブログ投稿Fabio Akita による記事には、この変更に関する有益な情報が記載されています (「最適化された Eager Loading」というセクションを参照)。