ホームページ  >  記事  >  PHPフレームワーク  >  Laravel で最も遅いクエリを見つける方法の簡単な分析

Laravel で最も遅いクエリを見つける方法の簡単な分析

青灯夜游
青灯夜游転載
2022-09-08 10:09:002485ブラウズ

あなたのウェブサイトは遅いですか?ロードに時間がかかりますか?ユーザーは、ほとんど 使い物にならない と不満を抱いていますか?データベースのクエリを確認する必要があります。すべてのデータベース クエリを簡単に分析する優れた方法を紹介します。

Laravel で最も遅いクエリを見つける方法の簡単な分析

もちろん、Web サイトが遅い理由はたくさんありますが、最も一般的な理由の 1 つはデータベース クエリの遅さです。

しかし、laravelでは、(ほとんどの場合)データベースからデータを取得するためにSQLを使用せず、Eloquent ORMクエリビルダーを使用します。このため、サイトの速度が大幅に遅くなる原因となっているクエリを特定することが困難になる場合があります。

DB::listen()

幸いなことに、laravel では、クエリが実行されるたびに呼び出される関数を定義できます。コールバック (ここを参照)。これを行うには、次のコードを任意のサービス プロバイダー (AppServiceProvider など) に追加します。

public function boot()
{
    DB::listen(function ($query) {
    // TODO: make this useful
    });
}

ご覧のとおり、変数 $query を受け取ります。この変数は インスタンスです。 QueryExecuted クラスの。これは、実行されたクエリに関するいくつかの情報にアクセスできることを意味します。

 DB::listen(function ($query) {
     $query->sql; // 执行的 sql 字符串
     $query->bindings; // 传递给sql查询的参数(这将替换sql字符串中的 "?")
     $query->time; // 执行查询所用的时间;
 });

これは非常に役立つ情報です。$query->time プロパティを確認することで、遅いクエリを特定できるようになりました。 しかし、これではコード内のどこで クエリが実行されるかがわかりません。

クエリがどこで実行されたかを知るにはどうすればよいですか?

$query 変数からソースに関する情報が得られない場合でも、PHP 組み込み関数 debug_backtrace() を使用できます。その情報を得るために。

DB::listen(function ($query) {
    dd(debug_backtrace());
});

これをプロジェクトで実行すると、ブラウザ上に次のようなものが表示されます。

array:63 [▼
  0 => array:7 [▼
 "file"=>"/home/cosme/Documents/projects/cosme.dev/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php"
    "line" => 404
    "function" => "App\Providers\{closure}"
    "class" => "App\Providers\AppServiceProvider"
    "object" => App\Providers\AppServiceProvider {#140 ▶}
    "type" => "->"
    "args" => array:1 [▶]
  ]
  1 => array:7 [▼
    "file" => "/home/cosme/Documents/projects/cosme.dev/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php"
    "line" => 249
    "function" => "Illuminate\Events\{closure}"
    "class" => "Illuminate\Events\Dispatcher"
    "object" => Illuminate\Events\Dispatcher {#27 ▶}
    "type" => "->"
    "args" => array:2 [▶]
  ]
  2 => array:7 [▼
    "file" => "/home/cosme/Documents/projects/cosme.dev/vendor/laravel/framework/src/Illuminate/Database/Connection.php"
    "line" => 887
    "function" => "dispatch"
    "class" => "Illuminate\Events\Dispatcher"
    "object" => Illuminate\Events\Dispatcher {#27 ▶}
    "type" => "->"
    "args" => array:1 [▶]
  ]
  ....

これは、各関数呼び出しのリクエストにおけるこれまでの値を含む配列です。各配列の file キーと line キーに注目します。

注意深く見ると、この例には 63 個の関数呼び出しがあることがわかります。これは単純なアプリケーションですが、より複雑なアプリケーションではさらに多くなる可能性があります。さらに悪いことに、上部にあるものを見ると、それらはすべてlaravelフレームワークの内部関数です。役立つものが見つかるまで、それぞれを検討する必要がありますか?

クエリの場所の検索前に述べたように、それらのほとんどは内部フレームワーク呼び出しです。つまり、これらのファイルのほとんどは

vendor/

ディレクトリ。これは、各 file をチェックし、次のように vendor/ による呼び出しを除外できることを意味します。 <pre class="brush:php;toolbar:false">DB::listen(function ($query) {     $stackTrace = collect(debug_backtrace())-&gt;filter(function ($trace) {         return !str_contains($trace['file'], 'vendor/');     });     dd($stackTrace); });</pre>ここでは、

を使用するために配列を Collection に変換します。 filter

メソッドで、file 現在 $tracevendor/ がある場合、それをコレクションから削除します。 上記のコードを実行すると、次のような内容が表示されます:

Illuminate\Support\Collection {#1237 ▼
  #items: array:5 [▼
    12 => array:7 [▼
      "file" => "/home/cosme/Documents/projects/cosme.dev/app/Models/Post.php"
      "line" => 61
      "function" => "get"
      "class" => "Illuminate\Database\Eloquent\Builder"
      "object" => Illuminate\Database\Eloquent\Builder {#310 ▶}
      "type" => "->"
      "args" => []
    ]
    16 => array:6 [▶]
    17 => array:6 [▶]
    61 => array:7 [▶]
    62 => array:4 [▶]
  ]
  #escapeWhenCastingToString: false
}

項目は大幅に減り、63 個からわずか 5 個になりました。最も重要な点は、コレクション内の最初の項目が、SQL クエリをトリガーする正確な場所であることです。これは、この情報を抽出して最も遅いクエリを見つけることができることを意味します。

ログに出力必要な情報がすべて揃ったので、ログに記録して、最も遅い問い合わせを確認して見つけます。 ? :

public function boot()
{
    DB::listen(function ($query) {
        $location = collect(debug_backtrace())->filter(function ($trace) {
            return !str_contains($trace['file'], 'vendor/');
        })->first(); // grab the first element of non vendor/ calls

        $bindings = implode(", ", $query->bindings); // format the bindings as string

        Log::info("
            ------------
            Sql: $query->sql
            Bindings: $bindings
            Time: $query->time
            File: ${location['file']}
            Line: ${location['line']}
            ------------
        ");
    });
}

これをアプリケーションで使用している場合は、ログ ファイルを確認すると、次のようなクエリ情報が表示されるはずです。

[2022-02-03 02:20:14] local.INFO:
------------
Sql: select "title", "slug", "body" from "posts" where "published" = ? order by "id" desc   
Bindings: 1
Time: 0.18
File: /home/cosme/Documents/projects/cosme.dev/app/Models/Post.php
Line: 61
----------

これで、どのクエリが最も遅いかがわかり、処理を開始できます。それらを 1 つずつ高速化するか、少なくともキャッシュするようにしてください。

拡張デバッグこれはデバッグに便利ですが、この手法はさまざまな方法で使用できます。

その週の最も遅いクエリを示す週次レポートを作成できます。

クエリが時間しきい値を超えると、スラック アラートを受け取る場合があります。

あなたとあなたのチームが毎回表示できるダッシュボードを作成できます。クエリが実行されました

#空には限界がありません。

[関連する推奨事項:

laravel ビデオチュートリアル

]

以上がLaravel で最も遅いクエリを見つける方法の簡単な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlearnku.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。