首頁  >  文章  >  php框架  >  淺析Laravel 中怎麼找到最慢的查詢

淺析Laravel 中怎麼找到最慢的查詢

青灯夜游
青灯夜游轉載
2022-09-08 10:09:002398瀏覽

你的網站慢嗎?加載需要很長時間嗎?用戶是否抱怨它幾乎 無法使用 ?您應該檢查您的資料庫查詢。我將向您展示一種輕鬆分析所有資料庫查詢的簡潔方法。

淺析Laravel 中怎麼找到最慢的查詢

當然,您的網站速度慢的原因有很多,但最常見的原因之一是資料庫查詢速度慢。

但是在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 [▶]
  ]
  ....

這是一個數組,其中包含請求中到目前為止的每個函數呼叫。我將只關注每個數組中的 fileline 鍵。

如果你仔細看,你會發現在我的例子中有 63 個函數調用,這是一個簡單的應用程序,如果在更複雜的應用程式中,可能會更多。更糟的是,如果您查看頂部的那些,它們都是 laravel 框架的內部函數。我們是否應該逐一查看,直到找到可能對我們有幫助的東西?

查找查詢位置

正如我之前所說,它們中的大多數是內部框架調用,這意味著這些文件中的大多數都在我們的vendor/ 目錄中。這意味著我們可以檢查每個file 並過濾掉任何具有vendor/ 的調用,如下所示:

DB::listen(function ($query) {
    $stackTrace = collect(debug_backtrace())->filter(function ($trace) {
        return !str_contains($trace['file'], 'vendor/');
    });

    dd($stackTrace);
});

在這裡,我將數組轉換為集合以使用該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
----------

現在您知道哪些查詢是最慢的,並開始一一處理它們,嘗試使它們更快,或至少快取它們。

擴展偵錯

這對於偵錯非常有用,但這種技術可以以多種方式使用。

您可以建立顯示一週中最慢查詢的每週報表。

如果查詢超過時間閾值,您可能會收到鬆弛警報

您可以建立一個儀表板,您和您的團隊可以在其中查看執行的每個查詢

天空才是極限。

【相關推薦:laravel影片教學

以上是淺析Laravel 中怎麼找到最慢的查詢的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:learnku.com。如有侵權,請聯絡admin@php.cn刪除
上一篇:laravel是aop嗎下一篇:laravel是aop嗎