「あー、N+1問題ね。うんうん...もちろん考慮すべきだね」
と言いつつ朧げな理解のままここまで生きてきました。
歴が長くなるにつれこういう基本的なことを知らないのがバレると恥ずかしいので
恥をかく前にちゃんと理解しておこう。
eager_load
指定したassociationをLEFT OUTER JOINでキャッシュする
orders.eager_load(:order_items)
SELECT
`orders`.`id` AS t0_r0,
`orders`.`store_account_id` AS t0_r1
FROM
`orders`
LEFT OUTER JOIN `order_items` ON `order_items`.`order_id` = `orders`.`id`;
preload
ordersテーブルからデータを取得
取得してきたorder
のidを持つorder_items
をIN句で取得
クエリが2回実行される
orders.pre_load(:order_items)
SELECT `orders`.* FROM `orders`;
SELECT
`order_items`.*
FROM
`order_items`
WHERE
`order_items`.`order_id` IN(1, 2, 3, ...);
includes
基本的にはpreload
を実行
下記いずれかの条件を満たす場合はeager_load
を実行
・includes
したテーブルでwhere句などを使用して条件を絞った場合
・includes
したassociationに対して、joins
かreferences
を呼んでいる場合
・任意のassociationに対してeager_load
メソッドを呼んでいる場合
めっちゃ簡単に使い分けするなら
・order :order_items(1 : n)など関連データがhas_manyの関係の場合preload
・store_accounts : user(n : 1)など関連データにbelongs_toの関係の場合eager_load
・指定したassociationに対してwhereしたいならeager_load
かincludes
まとめ
ただ動くコードを書けばいいのではなく、意味を理解してパフォーマンスも意識して実装しなきゃですね。
自身の理解のため端折って書いてる部分もあるので指摘があれば教えていただけますと幸いです!
詳しく理解されたい方は参考記事をご参照ください。