不知道大家是否和我一樣,在開發的過程中經常想看看產生的 SQL 語句有多少,又或者檢視到某一個 SQL 語句很慢的時候,需要定位到對應的程式碼位置去進行修改。有一些現成的工具幫我們做了這些事,比如 barryvdh/laravel-debugbar,但可能有時候我們只是想看一看 SQL,其他的東西不是太關心。
鑑於以上原因,自己寫了一個包,來幫助自己定位程式碼產生的 SQL,以便做一些最佳化什麼的。有興趣的可以用一下。程式碼在 sql-logger。
一個記錄 SQL 語句的工具,也可以記錄
jenssegers/mongodb
包產生的語句。
用途
記錄某一個 SQL 語句產生於哪一行程式碼。
記錄 MySQL 或者 MongoDB 產生的語句及其耗時。
安裝
1.透過 composer 安裝 (eleven26/sql-logger)。
composer require "eleven26/sql-logger:~1.0.0" --dev
2.註冊 Service Provider
Laravel
: 修改檔案config/app.php
,Laravel 5.5+
不需要'providers' => [ //... Eleven26\SqlLogger\SqlLoggerServiceProvider::class, ],
Lumen
: 修改檔案bootstrap/app.php
,新增下面這一行$app->register(Eleven26\SqlLogger\SqlLoggerServiceProvider::class);
- 在
config
資料夾下面新增一個配置檔案,名為sql-logger.php
,複製如下內容進去:
<?php
return [
// 是否啟用 sql-logger
'enable_sql_logger' => env('ENABLE_SQL_LOGGER', true),
// config/database.php connections 裡面配置的連線名
'mysql_connections' => [
],
// config/database.php connections 裡面配置的連線名
'mongodb_connections' => [
],
];
用法
下面提到的資料庫連線名來自於
config/database.php
裡面connections
陣列的鍵。
監聽
- 首先在配置檔案
config/sql-logger.php
裡面新增連線名稱,MySQL 連線名加到mysql_connections
陣列中,如:
'mysql_connections' => [
"user",
],
- 如果需要啟用 MongoDB 的監聽,在
mongodb_connections
陣列中新增對應的連線名即可。
如何啟用監聽
使用
enable_mysql_log
來監聽 MySQL 產生的 SQL 語句,使用enable_mongo_log
來監聽 MongoDB 產生的語句。如果只是想對某幾行程式碼進行除錯,可以在那幾行程式碼之後使用
disable_mysql_log
或者disable_mongo_log
來禁用後續 SQL 語句的記錄。
如何定位 SQL 語句產生的地方
有時候我們看到程式碼產生了一些慢查詢、重複查詢等,這個時候我們想去定位是哪一行程式碼產生的話。可以給 enable_mysql_log
或 enable_mongo_log
傳入一個引數,引數內容是 SQL 語句的一部分,最好是可以完全和輸出的其他 SQL 區分開的。
寫 Log 的時候,會判斷當前要記錄的 SQL 語句是否包含了傳遞的引數字串,如果包含,則記錄產生該 SQL 的堆疊。這樣我們就知道是哪一行程式碼導致了這個 SQL 語句的出現。
例項
- 模型
class User extends Model
{
protected $connection = 'user';
}
config/database.php
return [
// ...
"connections" => [
"user" => [
// ...具體配置項
]
],
// ...
];
- 記錄 SQL 語句及其時間:
enable_mysql_log();
app(User::class)->first();
- 檢視日誌檔案,可以看到如下內容:
[2020-07-26 20:13:59] lumen.INFO: time: 37.42ms select * from `users` where `users`.`deleted_at` is null limit 1
- 檢視這個 SQL 語句是哪一行產生的,只需要給
enable_mysql_log
傳遞 SQL 語句中可以區別開其他 SQL 語句的子字串進去即可,如:
enable_mysql_log('select * from `users`');
app(User::class)->first();
再次檢視日誌檔案可以看到如下內容:
[2020-07-26 20:16:42] lumen.INFO: time: 30.40ms select * from `users` where `users`.`deleted_at` is null limit 1
[2020-07-26 20:16:42] lumen.INFO:
#0 /Users/ruby/code/Foundation/vendor/illuminate/events/Dispatcher.php(350): Eleven26\SqlLogger\MysqlLogService::Eleven26\SqlLogger\{closure}(Object(Illuminate\Database\Events\QueryExecuted))
#1 /Users/ruby/code/Foundation/vendor/illuminate/events/Dispatcher.php(200): Illuminate\Events\Dispatcher->Illuminate\Events\{closure}('Illuminate\\Data...', Array)
#2 /Users/ruby/code/Foundation/vendor/illuminate/database/Connection.php(825): Illuminate\Events\Dispatcher->dispatch('Illuminate\\Data...')
#3 /Users/ruby/code/Foundation/vendor/illuminate/database/Connection.php(682): Illuminate\Database\Connection->event(Object(Illuminate\Database\Events\QueryExecuted))
#4 /Users/ruby/code/Foundation/vendor/illuminate/database/Connection.php(635): Illuminate\Database\Connection->logQuery('select * from `...', Array, 214.4)
#5 /Users/ruby/code/Foundation/vendor/illuminate/database/Connection.php(333): Illuminate\Database\Connection->run('select * from `...', Array, Object(Closure))
#6 /Users/ruby/code/Foundation/vendor/illuminate/database/Query/Builder.php(1719): Illuminate\Database\Connection->select('select * from `...', Array, true)
#7 /Users/ruby/code/Foundation/vendor/illuminate/database/Query/Builder.php(1704): Illuminate\Database\Query\Builder->runSelect()
#8 /Users/ruby/code/Foundation/vendor/illuminate/database/Eloquent/Builder.php(481): Illuminate\Database\Query\Builder->get(Array)
#9 /Users/ruby/code/Foundation/vendor/illuminate/database/Eloquent/Builder.php(465): Illuminate\Database\Eloquent\Builder->getModels(Array)
#10 /Users/ruby/code/Foundation/vendor/illuminate/database/Concerns/BuildsQueries.php(77): Illuminate\Database\Eloquent\Builder->get(Array)
#11 /Users/ruby/code/Foundation/vendor/illuminate/database/Eloquent/Model.php(1477): Illuminate\Database\Eloquent\Builder->first()
#12 /Users/ruby/code/Foundation/test.php(9): Illuminate\Database\Eloquent\Model->__call('first', Array)
#13 {main}
這裡的第二條 log 記錄了 SQL 語句產生的堆疊,開發者可以依據這些資料來精確判定是哪一行產生的 SQL。
最佳實踐
執行
composer require
的時候,加上--dev
生產配置檔案
.env
中,加上配置:ENABLE_SQL_LOGGER=false
本作品採用《CC 協議》,轉載必須註明作者和本文連結