Laravel 9 保姆級視訊教學,想學不會都難!進入學習
當然,您的網站速度慢的原因有很多,但最常見的原因之一是資料庫查詢速度慢。
但是在 laravel 中,我們(大多數時候)不使用 SQL 從資料庫中獲取資料,我們使用 Eloquent ORM 和 查詢構建器 ,這有時會導致很難查明造成我們網站如此緩慢的查詢。
幸運的是,在 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/
的呼叫,如下所示:
DB::listen(function ($query) { $stackTrace = collect(debug_backtrace())->filter(function ($trace) { return !str_contains($trace['file'], 'vendor/'); }); dd($stackTrace); });
在這裡,我將陣列轉換為集合以使用該 filter
方法,如果 file
當前 $trace
有 vendor/
我們將其從集合中刪除。
如果您執行上面的程式碼,您將看到如下內容:
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 中怎麼找到最慢的查詢的詳細內容,更多請關注TW511.COM其它相關文章!