SHOW VARIABLES LIKE 'slow%';
slow_query_log:ON/OFFslow_query_log_file:日誌文件路徑long_query_time:閾值 (秒),預設 10sSET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 2; -- 記錄超過 2 秒的查詢
[mysqld]
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
log_queries_not_using_indexes = ON -- 記錄未用索引查詢 (慎用,量大)
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log:按耗時排序 Top 10。pt-query-digest (Percona Toolkit):專業分析、聚合、報告。INT 優於 BIGINT,CHAR(10) 優於 VARCHAR(255)。type (system/const/eq_ref/ref/range/index/ALL)、key、rows、Extra (Using index/Using where/Using temporary/Using filesort)。| 場景 | 錯誤寫法 | 正確寫法 | 原因 |
|---|---|---|---|
| 不等於 | WHERE status != 1 | WHERE status IN (0,2,3) 或 UNION | != 導致全表掃描 |
| 函數/表達式作用於列 | WHERE DATE(create_time) = '2023-01-01' | WHERE create_time >= '2023-01-01' AND create_time < '2023-01-02' | 函數破壞索引順序 |
| 隱式類型轉換 | WHERE phone = 13800000000 (phone 是 VARCHAR) | WHERE phone = '13800000000' | 字串轉數字導致索引失效 |
| LIKE 以 % 開頭 | WHERE name LIKE '%張%' | 全文索引 / Elasticsearch | B+樹無法利用前綴匹配 |
| LIKE 固定前綴 | WHERE name LIKE '張%' | 同上 (索引生效) | 前綴匹配可用索引 |
| OR 條件列無索引 | WHERE a=1 OR b=2 (b 無索引) | UNION ALL 分開查詢 | OR 要求兩側都有索引才用 index_merge |
| IS NULL / IS NOT NULL | WHERE col IS NULL | 可用索引 (MySQL 支援) | 注意 NOT NULL 列優化 |
[ ] 1. EXPLAIN 確認 type 非 ALL/index
[ ] 2. key 欄位顯示預期索引
[ ] 3. rows 預估行數合理 (非全表)
[ ] 4. Extra 無 Using temporary / Using filesort
[ ] 5. WHERE 條件無函數/隱式轉換/!=/前導%
[ ] 6. 覆蓋索引優化 (Using index)
[ ] 7. 大表 DDL 走 pt-online-schema-change
[ ] 8. 慢查詢日誌定期 pt-query-digest 分析
慢查詢優化核心是「讓索引生效」+「減少掃描行數」+「避免臨時表/文件排序」。建立「開啟慢查詢 → 定期分析 → EXPLAIN 驗證 → 改寫 SQL/調索引 → 壓測驗證」的閉環流程,是 DBA 與開發共同的責任。