您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“Laravel中如何找到最慢查詢”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!
幸運的是,在 laravel 中,我們可以定義一個在每次執(zhí)行查詢時調(diào)用的回調(diào)(參見 此處)。為此,請將以下代碼添加到任何服務(wù)提供者(例如 AppServiceProvider):
public function boot()
{
DB::listen(function ($query) {
// TODO: make this useful
});
}
如您所見,我們接收了一個變量 $query
,這個變量是 QueryExecuted 類的一個實例。這意味著我們可以訪問有關(guān)已執(zhí)行查詢的一些信息:
DB::listen(function ($query) {
$query->sql; // 執(zhí)行的 sql 字符串
$query->bindings; // 傳遞給sql查詢的參數(shù)(這將替換sql字符串中的 "?")
$query->time; // 執(zhí)行查詢所用的時間;
});
這是非常有用的信息,現(xiàn)在我們可以通過查看 $query->time
屬性來識別慢查詢。 但這并沒有告訴我們在我們的代碼中查詢執(zhí)行的位置。
即使該 $query
變量沒有給我們?nèi)魏侮P(guān)于其來源的信息, 我們?nèi)匀豢梢允褂?PHP 內(nèi)置函數(shù) 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 [?]
]
....
這是一個數(shù)組,其中包含請求中到目前為止的每個函數(shù)調(diào)用。我將只關(guān)注每個數(shù)組中的 file
和 line
鍵。
如果你仔細看,你會發(fā)現(xiàn)在我的例子中有 63 個函數(shù)調(diào)用,這是一個簡單的應(yīng)用程序,如果在更復(fù)雜的應(yīng)用程序中,可能會更多。更糟糕的是,如果您查看頂部的那些, 它們都是 laravel 框架的內(nèi)部函數(shù)。我們是否應(yīng)該逐一查看,直到找到可能對我們有幫助的東西?
正如我之前所說,它們中的大多數(shù)是內(nèi)部框架調(diào)用,這意味著這些文件中的大多數(shù)都在我們的 vendor/
目錄中。這意味著我們可以檢查每個 file
并過濾掉任何具有 vendor/
的調(diào)用,如下所示:
DB::listen(function ($query) {
$stackTrace = collect(debug_backtrace())->filter(function ($trace) {
return !str_contains($trace['file'], 'vendor/');
});
dd($stackTrace);
});
在這里,我將數(shù)組轉(zhuǎn)換為集合以使用該 filter
方法,如果 file
當前 $trace
有 vendor/
我們將其從集合中刪除。
如果您運行上面的代碼,您將看到如下內(nèi)容:
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 個。最好的部分是集合中的第一項是我們觸發(fā) 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']}
------------
");
});
}
如果您在應(yīng)用程序中使用它,您可以檢查您的日志文件,您應(yīng)該會看到如下查詢信息:
[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
----------
現(xiàn)在您知道哪些查詢是最慢的,并開始一一處理它們,嘗試使它們更快,或者至少緩存它們。
這對于調(diào)試非常有用,但這種技術(shù)可以以多種方式使用。
您可以創(chuàng)建顯示一周中最慢查詢的每周報告。
如果查詢超過時間閾值,您可能會收到松弛警報
您可以創(chuàng)建一個儀表板,您和您的團隊可以在其中查看執(zhí)行的每個查詢
天空才是極限。
“Laravel中如何找到最慢查詢”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。