DB利用した実装している際に注意しながらも見落としてしまうN+1問題ですが、自動的に検出してくれるツールがあるのでご紹介します。
Laravel N+1 Query Detector
composer経由でインストール出来ます。
composer require beyondcode/laravel-query-detector --dev
そのままでもすぐに使用できますが、折角なので設定変更しましょう/vendor/beyondcode/laravel-query-detector/config/config.php
から /config/querydetector.php
へ、
configファイルが生成されます。
php artisan vendor:publish --provider=BeyondCode\\QueryDetector\\QueryDetectorServiceProvider
デフォルトではアラートとログファイルに検知内容が表示されますが、今回はコンソールにも表示させたいと思います。
設定ファイルの `output` の箇所に追記します。
'output' => [ // 画面上でアラートを検知内容を表示 \BeyondCode\QueryDetector\Outputs\Alert::class, // ログファイルに検知内容を表示 \BeyondCode\QueryDetector\Outputs\Log::class, // コンソール上に検知内容を表示 \BeyondCode\QueryDetector\Outputs\Console::class, // 追記 ]
N+1を発生させて、検知させてみたいと思います。
適当なコントローラーとモデルを作成します。
class Member extends Model { public function comments() { return $this->hasMany(Comment::class, 'member', 'id'); } }
class Comment extends Model { public function members() { return $this->belongsTo(Member::class, 'member', 'id'); } }
class Member extends Controller { public function index() { // Memberモデルの取得 $members = \App\Models\Member::all(); foreach ($members as $member) { // リレーションでCommentモデルを取得 // Memberモデルの数だけクエリが作成される(N+1) $comments = $member->comments; } return view('member.index',compact( 'members', )); } }
以下の様に検知出来ています
configファイルに以下の記述があります。
環境変数にQUERY_DETECTOR_ENABLEDを定義しなければ、環境変数APP_DEBUGを見て、検知内容の表示/非表示を分けている様です。
/* * Enable or disable the query detection. * If this is set to "null", the app.debug config value will be used. */ 'enabled' => env('QUERY_DETECTOR_ENABLED', null),
N+1を見落とす確率が大分減ると思うので、こうしたツールは積極的に利用したいですね。