laravelでsqlのログを出力した際n+1問題が出てきた。
LaravelはデフォルトでSQLのログを出力してくれないので
SQLログを出力する方法を記載します。
App\Providers直下に記載します
デフォルトでは
use Illuminate\Support\Facades\Schema;
use DB;
が入っていない可能性があります。
App\Providers
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Schema; <-ココ追記
use Illuminate\Support\ServiceProvider;
use DB; <-ココ追記
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot() {
# 本番環境以外だった場合、SQLログを出力する
if (config('app.env') !== 'production') {
DB::listen(function ($query) {
\Log::info("Query Time:{$query->time}s] $query->sql");
});
}
}
/**
* Register any application services.
*
* @return void
*/
public function register() {
//
}
}
一度画面の更新をすると
laravelファイル直下のstorage/logsに作成されます
この際sqlが大量に発行されて重くなるというのがn+1問題です。
sqlテーブルが2つあって片方を片方に代入するときに大量にログが出てしまいます。
これを解決するにはApp\Http\Controllersのsqlデータを呼び出している部分にwithを書くこと
$posts = Post::orderBy('created_at', 'desc')
->categoryAt($category_id)
->paginate(10);
↓↓↓↓↓ 以下に変更 ↓↓↓↓↓
$posts = Post::with('foods') // ←★これ
->orderBy('created_at', 'desc')
->categoryAt($category_id)
->paginate(10);
筆者は1対多のsqlだったので、Post::with('foods')
foodsとsをつけて複数形にしています。
第二引数、第三引数があるのならば
$posts = Post::orderBy('created_at', 'desc')
->categoryAt($category_id)
->paginate(10);
↓↓↓↓↓ 以下に変更 ↓↓↓↓↓
$posts = Post::with(['foods', 'drink']) // ←★これ
->orderBy('created_at', 'desc')
->categoryAt($category_id)
->paginate(10);
これでn+1問題が解決されます。
もっと詳しく見たい方はこの記事
https://qiita.com/TsubasaTakagi/items/8c3f4317ad917924b860