1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】N + 1問題についてそろそろちゃんと向き合わなきゃな...

Last updated at Posted at 2024-11-09

「あー、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に対して、joinsreferencesを呼んでいる場合
・任意のassociationに対してeager_loadメソッドを呼んでいる場合

めっちゃ簡単に使い分けするなら

・order :order_items(1 : n)など関連データがhas_manyの関係の場合preload
・store_accounts : user(n : 1)など関連データにbelongs_toの関係の場合eager_load
・指定したassociationに対してwhereしたいならeager_loadincludes

まとめ

ただ動くコードを書けばいいのではなく、意味を理解してパフォーマンスも意識して実装しなきゃですね。
自身の理解のため端折って書いてる部分もあるので指摘があれば教えていただけますと幸いです!
詳しく理解されたい方は参考記事をご参照ください。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?