慢查詢日志是 SQL 調優的「體檢報告」。本文詳細講解 long_query_time 動態調整、配置文件持久化啟用、5.0/5.5+ 版本差異、EXPLAIN 輸出各列含義、典型執行計劃模式識別,讓你從「感覺慢」進化到「數據驅動優化」。
SHOW VARIABLES LIKE 'long_query_time';
+-----------------+----------+
| Variable_name | Value |
+-----------------+----------+
| long_query_time | 10.000000 |
+-----------------+----------+
SET GLOBAL long_query_time = 1; -- 建議 1-2 秒
SET GLOBAL long_query_time = 0.5; -- 高併發核心業務可設亞秒級
[mysqld]
# 5.0 / 5.1
log-slow-queries = /var/log/mysql/slow.log
long_query_time = 1
# 5.5 / 5.6 / 5.7 / 8.0
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = ON
min_examined_row_limit = 100
不僅限 SELECT:INSERT、UPDATE、DELETE、CALL、REPLACE 等所有 DML/DDL 超時均會記錄。
EXPLAIN SELECT * FROM admin WHERE user_id = 1\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: admin
partitions: NULL
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
filtered: 100.00
Extra:
1 row in set (0.00 sec)
| 列 | 含義 | 關鍵判讀 |
|---|---|---|
| id | 查詢序號,同 id 從上到下執行 | 相同 id 為同一查詢塊 |
| select_type | 查詢類型:SIMPLE/PRIMARY/SUBQUERY/DERIVED/UNION 等 | SUBQUERY/DEPENDENT SUBQUERY 易成性能殺手 |
| table | 訪問的表(或衍生表 | 關注訪問順序 |
| partitions | 分區表匹配的分區 | 分區裁剪驗證 |
| type | 訪問類型(核心指標) | system > const > eq_ref > ref > range > index > ALL |
| possible_keys | 理論可用索引 | 為空 = 無索引可用 |
| key | 實際使用索引 | NULL = 全表掃描 |
| key_len | 使用索引長度(字節) | 推斷聯合索引用了幾列 |
| ref | 與索引比較的列/常量 | const = 常量,col = 關聯列 |
| rows | 預估掃描行數 | 越小越好,統計信息不準時偏差大 |
| filtered | 按表條件過濾後剩餘比例% | 低值 = 回表後大量過濾 |
| Extra | 額外信息 | Using index / Using where / Using temporary / Using filesort |
>, >=, IN, BETWEEN)type = ALL → 加索引或改寫 SQLUsing filesort → 為 ORDER BY 列加索引,或 LIMIT 限制排序規模Using temporary → 增加索引消除臨時表,或調大 tmp_table_sizekey_len 遠小於索引定義長度 → 聯合索引未命中最左列rows 極大但 filtered 很低 → 索引選擇性差,考慮強制索引或重構-- Oracle
EXPLAIN PLAN FOR SELECT * FROM admin WHERE user_id = 1;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
養成「寫 SQL 必跑 EXPLAIN」習慣,將性能風險消滅在開發階段。