railsでN+1問題を解決するpreload, eager_load, includes
preload
code:ruby
Store.preload(:products)
発行されるSQL
# Store Load (3.0ms) SELECT stores.* FROM stores LIMIT 11
# Product Load (1.2ms) SELECT products.* FROM products WHERE products.store_id IN (1, 2, 3, 4, 6)
eager_load
code:ruby
Store.eager_load(:products)
発行されるSQL
# SQL (2.2ms) SELECT DISTINCT stores.id FROM stores LEFT OUTER JOIN products ON products.store_id = stores.id LIMIT 11
# SQL (4.5ms) SELECT stores.id AS t0_r0, stores.email AS t0_r1, stores.encrypted_password AS t0_r2, stores.storename
LEFT OUTER JOINによってデータが取り出されキャッシュされるので、1対NやN対Nの場合アソシエーション先のテーブル数に応じて同じだけレコードが取得されるのでその分速度が遅くなる可能性があります。
一方で、1対1やN対1の場合は無駄なテーブルの取得が起こらないのでSQLの発行回数が少ない分preloadよりもパフォーマンスが良いです。
また、LEFT OUTER JOINでは両テーブルのカラムが取得されるのでアソシエーション先のカラムで絞り込みを行うことが可能です。