IT-Q

前問の N+1 を解消する Eloquent の書き方はどれですか。

with() でリレーションを事前ロードすると、101本だったクエリが2本になります。親を1本取り、子を whereIn で1本まとめて取る、という中身まで説明できると面談で通ります。

面接官が見ているのは用語を知っているだけでなく、対処法とセットで覚えているか。

よくある答えと、面談でどう見られるか

  • Post::with('user')->get() で関連を事前にまとめて取る
    Eager Loading です。posts 1本+users を IN でまとめて1本の計2本になります。
  • Post::all() の結果を foreach ではなく for で回す
    ループの書き方は関係ありません。ループ内でDBに行くこと自体が原因です。
  • users テーブルにインデックスを貼る
    1本あたりは速くなりますが、本数は減りません。
  • 結果を Cache::remember() でキャッシュする
    症状を隠すだけで、原因は残ったままです。

模範解答

with() でリレーションを事前ロード(Eager Loading)します。

  $posts = Post::with('user')->get();
  // SELECT * FROM posts
  // SELECT * FROM users WHERE id IN (1, 2, 3, ...)

101本が2本になります。開発中に検知したい場合はModel::preventLazyLoading() を有効にすると、遅延ロード時に例外が飛びます。