詳解Laravel中怎么找到最慢查詢

詳解Laravel中怎么找到最慢查詢

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

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

但是在 laravel 中,我們(大多數時候)不使用 sql 從數據庫中獲取數據,我們使用 Eloquent ORMEloquent ORM ,這有時會導致很難查明造成我們網站如此緩慢的查詢。【相關推薦:Eloquent ORM

DB::listen()

幸運的是,在 laravel 中,我們可以定義一個在每次執行查詢時調用的回調(參見 Eloquent ORM)。為此,請將以下代碼添加到任何服務提供者(例如 AppServiceProvider):

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

如您所見,我們接收了一個變量 $query,這個變量是 Eloquent ORM 類的一個實例。這意味著我們可以訪問有關已執行查詢的一些信息:

?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"?=>?"AppProviders{closure}" ????"class"?=>?"AppProvidersAppServiceProvider" ????"object"?=>?AppProvidersAppServiceProvider?{#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"?=>?"IlluminateEvents{closure}" ????"class"?=>?"IlluminateEventsDispatcher" ????"object"?=>?IlluminateEventsDispatcher?{#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"?=>?"IlluminateEventsDispatcher" ????"object"?=>?IlluminateEventsDispatcher?{#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/ 我們將其從集合中刪除。

如果您運行上面的代碼,您將看到如下內容:

IlluminateSupportCollection?{#1237?▼ ??#items:?array:5?[▼ ????12?=>?array:7?[▼ ??????"file"?=>?"/home/cosme/Documents/projects/cosme.dev/app/Models/Post.php" ??????"line"?=>?61 ??????"function"?=>?"get" ??????"class"?=>?"IlluminateDatabaseEloquentBuilder" ??????"object"?=>?IlluminateDatabaseEloquentBuilder?{#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 ----------

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

擴展調試

這對于調試非常有用,但這種技術可以以多種方式使用。

您可以創建顯示一周中最慢查詢的每周報告。

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

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

天空才是極限。

原文地址:https://dev.to/cosmeoes/how-to-find-the-slowest-query-in-your-application-4igb譯文地址:https://learnku.com/laravel/t/65164

更多編程相關知識,請訪問:Eloquent ORM!!

? 版權聲明
THE END
喜歡就支持一下吧
點贊10 分享