やる気がストロングZERO

やる気のストロングスタイル

【activerecord】joins, includes, eager_load, preloadの違い

joins, includes, eager_load, preloadはよく似た状況を作り出すがいまいち理解し切れなかったので整理。

参考) ActiveRecordのjoinsとpreloadとincludesとeager_loadの違い - Qiita

N+1問題を回避し、かつ、、
where条件に関連テーブルのカラムを使いたい場合はeager_load、
joinを使いたくない場合はpreload

N+1問題は考慮せず、単にwhere条件に関連テーブルのカラムを使いたい場合はjoinsを使うのが良さげかと思った。

◆joins

 Post.joins(:comments).where("comments.id = 1") 

・関連テーブルデータ先読みはしない
・inner joinを使った絞り込みをしたい時
・joinして1クエリを発行する

先読みしないのでN+1問題の解決にはならない。
※関連データにアクセスした時点でクエリが発行される。
where条件に関連テーブルのカラムを含めたい場合に使う感じ。

◆includes

Post.includes(:comments).where(comments: {id: 1}) 

・関連テーブルデータ先読みする
・条件によってjoinしたりしなかったりする

関連テーブルデータを先読みするので N+1問題の対策になる。
where条件に関連テーブルのカラムを含めたい場合、reference()を使うか、where条件をハッシュで書く必要がある。

◆eager_load

Post.eager_load(:comments).where("comments.id = 1") 

・データ先読みする。
・参照テーブルでの絞り込みok
・joinして1クエリ

関連テーブルデータを先読みするので N+1問題の対策になる。
where条件に関連テーブルのカラムを含められる。

◆preload

Post.preload(:comments) 

・データ先読みする
・参照テーブルでの絞り込みできない
・joinしない、複数クエリが発行される

関連テーブルデータを先読みするので N+1問題の対策になる。
where条件に関連テーブルのカラムを含められない。