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条件に関連テーブルのカラムを含められない。