慢查詢日志(Slow Query Log)是 MySQL 提供的一種核心性能優化工具,用于記錄執行時間超過指定閾值的 SQL 語句。通過分析這些日志,可以定位數據庫性能瓶頸,優化低效查詢,提升系統整體效率。
一、慢查詢日志的作用
- 性能瓶頸定位
識別執行時間過長的 SQL 語句,幫助找出數據庫性能問題的根源(如索引缺失、復雜查詢、全表掃描等)。 - 優化依據
提供真實的 SQL 執行數據(如執行時間、鎖等待時間、掃描行數等),為優化提供依據。 - 系統監控
監控數據庫長期性能變化趨勢,及時發現潛在問題。 - 索引優化
記錄未使用索引的查詢(需配置log_queries_not_using_indexes
),幫助發現索引缺失或無效使用的情況。
二、如何開啟慢查詢日志
1. 配置文件設置(永久生效)
編輯 MySQL 配置文件(my.cnf
或 my.ini
),在 [mysqld]
段中添加以下參數:
[mysqld]
slow_query_log = 1 # 開啟慢查詢日志(1 表示開啟)
slow_query_log_file = /path/to/slow.log # 指定日志文件路徑
long_query_time = 2 # 定義慢查詢閾值(單位:秒,默認 10 秒)
log_queries_not_using_indexes = 1 # 記錄未使用索引的查詢(可選)
log_output = FILE # 日志輸出方式(FILE 或 TABLE)
保存后重啟 MySQL 服務:
# Linux 系統
sudo systemctl restart mysqld
2. 動態設置(臨時生效)
通過 MySQL 命令行臨時啟用(重啟后失效):
-- 開啟慢查詢日志
SET GLOBAL slow_query_log = 'ON';
-- 設置慢查詢閾值(需重新連接會話才能生效)
SET GLOBAL long_query_time = 2;
-- 指定日志文件路徑
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
-- 記錄未使用索引的查詢
SET GLOBAL log_queries_not_using_indexes = 1;
3. 驗證配置
執行以下命令檢查配置是否生效:
SHOW VARIABLES LIKE 'slow_query%';
SHOW GLOBAL VARIABLES LIKE 'long_query_time';
三、核心參數詳解
參數名 | 類型 | 默認值 | 說明 |
---|---|---|---|
slow_query_log | Boolean | OFF | 慢查詢日志總開關 |
slow_query_log_file | String | hostname-slow.log | 慢查詢日志文件路徑 |
long_query_time | Float | 10 | 慢查詢閾值(單位:秒) |
log_queries_not_using_indexes | Boolean | OFF | 是否記錄未使用索引的查詢 |
min_examined_row_limit | Integer | 0 | 記錄掃描行數超過該值的查詢 |
log_slow_admin_statements | Boolean | OFF | 是否記錄慢管理語句(如 ALTER /ANALYZE ) |
log_slow_slave_statements | Boolean | OFF | 是否記錄從庫慢查詢 |
四、日志內容與格式
慢查詢日志記錄了以下信息:
- SQL 語句:被記錄的查詢語句。
- 執行時間(Query_time):SQL 執行的總時間。
- 鎖等待時間(Lock_time):SQL 等待鎖的時間。
- 返回行數(Rows_sent):返回給客戶端的行數。
- 掃描行數(Rows_examined):SQL 掃描的行數。
- 用戶信息:執行查詢的用戶和主機信息。
- 時間戳:查詢執行的日期和時間。
示例日志內容:
# Time: 2025-06-30T17:50:07.123456Z
# User@Host: root[root] @ localhost []
# Query_time: 2.345678 Lock_time: 0.000123 Rows_sent: 100 Rows_examined: 10000
SET timestamp=1720000000;
SELECT * FROM users WHERE created_at > '2025-01-01';
五、日志分析方法
1. 直接查看日志文件
使用命令行工具查看日志文件:
# 查看日志內容
less /var/log/mysql/slow.log# 統計慢查詢數量
grep -c "Query_time" /var/log/mysql/slow.log
2. 使用 MySQL 自帶工具 mysqldumpslow
mysqldumpslow
可以匯總和排序慢查詢日志中的 SQL 語句。
# 按執行時間排序,顯示前10條
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log# 按查詢次數排序,顯示前10條
mysqldumpslow -s c -t 10 /var/log/mysql/slow.log
3. 使用第三方工具 pt-query-digest
Percona Toolkit 中的 pt-query-digest
提供更詳細的分析報告:
pt-query-digest /var/log/mysql/slow.log > analysis_report.txt
4. 查詢 mysql.slow_log
表
如果日志輸出到表(log_output=TABLE
),可通過 SQL 直接查詢:
SELECT * FROM mysql.slow_log ORDER BY query_time DESC LIMIT 10;
六、優化慢查詢的典型方法
-
添加索引
對頻繁查詢的字段(如WHERE
、JOIN
、ORDER BY
)添加索引。
示例:CREATE INDEX idx_created_at ON users(created_at);
-
優化 SQL 語句
- 避免全表掃描(使用
EXPLAIN
分析執行計劃)。 - 減少子查詢,改用
JOIN
。 - 避免
SELECT *
,僅查詢必要字段。
- 避免全表掃描(使用
-
調整配置參數
- 根據業務需求調整
long_query_time
(例如設置為 1 秒)。 - 啟用
log_queries_not_using_indexes
以發現未使用索引的查詢。
- 根據業務需求調整
-
分頁與緩存
- 對高頻查詢結果進行緩存(如 Redis)。
- 使用分頁限制返回行數(如
LIMIT 100
)。
七、常見問題與注意事項
-
日志文件過大
- 定期歸檔或清理舊日志,避免磁盤空間不足。
- 使用
log_output=TABLE
將日志存儲到數據庫表中,便于管理。
-
生產環境配置建議
- 閾值設置:默認閾值為 10 秒,生產環境中建議調低(如 1-2 秒)以捕獲更多潛在問題。
- 權限問題:確保 MySQL 有權限寫入日志文件路徑。
- 性能影響:慢查詢日志本身會帶來輕微性能開銷,建議在測試環境調試,生產環境謹慎使用。
-
未使用索引的查詢
啟用log_queries_not_using_indexes
后,日志可能快速增長,需結合EXPLAIN
分析是否需要添加索引。
八、實戰案例
案例 1:索引優化
問題:查詢 created_at
范圍內的用戶列表耗時較長。
SELECT * FROM users WHERE created_at BETWEEN '2023-01-01' AND '2023-12-31';
優化:在 created_at
字段上創建索引。
CREATE INDEX idx_created_at ON users(created_at);
效果:查詢時間從 5 秒降至 0.1 秒。
案例 2:復雜查詢優化
問題:關聯查詢訂單和用戶表時響應時間過長。
SELECT o.id, o.total
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.order_date BETWEEN '2023-01-01' AND '2023-12-31';
優化:
-
在
order_date
字段上創建索引:CREATE INDEX idx_order_date ON orders(order_date);
-
使用覆蓋索引優化查詢:
SELECT o.id, o.total FROM orders o JOIN users u ON o.user_id = u.id WHERE o.order_date BETWEEN '2023-01-01' AND '2023-12-31' USE INDEX (idx_order_date);
效果:查詢時間從 3 秒降至 0.3 秒。
九、總結
慢查詢日志是 MySQL 性能優化的核心工具,通過合理配置和分析,可以顯著提升數據庫效率。建議結合 EXPLAIN
、索引優化和 SQL 重寫策略,持續監控和調優數據庫性能。
👍 不積跬步,無以至千里
😊 希望對你有幫助!