LoginSignup
1
0

More than 1 year has passed since last update.

Laravelでよく起こるらしいN + 1問題ってなんだ

Last updated at Posted at 2022-09-30

はじめに

この記事は「LaravelのEloquent便利だなー、リレーションの使い方を調べて見よう。ふむふむwithを使って書いとけばとりあえずいいんやな。」と、なぜwithを使えば良いかを対して理解せずに使っていたのでN + 1問題というものがなんなのか調べてみてわかったことをまとめる記事です。

環境

$ php artisan --version
Laravel Framework 8.36.2

$ php --version
PHP 8.0.23 (cli) (built: Sep 13 2022 11:09:24) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.23, Copyright (c) Zend Technologies

N + 1問題ってそもそもなに?

「N件のデータを取得し、それぞれに紐付くデータを取得する際にクエリを発行する回数がN + 1回になってしまうこと。」らしいです。
LaravelのようなORMがあるフレームワークを使用しているとSQLの発行回数等の意識が薄くなりがちだと思いますがパフォーマンスに大きく影響するのでEloquent等を使用する際は自身が発行しているSQLの内容をきちんと理解するのが大切ですね。(ブーメラン)

N + 1問題が起こっているコード1例

リレーションについて調べているとよく出てくるBookAuthorを例にしてかいてみます。
N件のBookを取得しそれぞれに紐付くAuthorを取得してみます。

// use, リレーションメソッド等は省略

$books = Book::all();
foreach ($books as $book) {
    $book->author;
}

はい、これN + 1問題起こってますよね!?って言っても見えないので見えるようにしてみます。


DB::enableQueryLog();

$books = Book::get();
foreach ($books as $book) {
    $book->author;
}

dd($books, DB::getQueryLog());

dd()の第2引数に渡しているDB::getQueryLog()で発行されたクエリを見ることができます。
Book取得で1回、Bookの件数分(N件)のAuthorを取得するのでN + 1回取得していることが確認できたと思います。
(*ログも出さないなんて不親切な記事なんだ)

N + 1問題の解決

Laravelではwithを使ってN + 1問題が発生しないようにできます。

DB::enableQueryLog();
$books = Book::with(['author'])->get();
dd($books, DB::getQueryLog());

確認するとBookAuthorそれぞれに1回ずつクエリが発行されていることがわかりました。めでたしめでたし。

おわりに

これを書いたきっかけが株式会社 ゆめみ様がwithについてソースコードリーディング会をされていたのでこっそり視聴させていただきました。(まったりな感じのソースコードリーディング会のようなものは参加しやすいので非常にありがたいですね。)
コードはなんとなくぎりぎりある程度・・・追うことができたのですが、Eager LoadingLazy Loadingと言った単語を良く分かっていなかったため理解しておこうと思い色々調べたので記事にしました。それでは。

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