首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 優化器問題排查實戰:EXPLAIN 執行計畫、ANALYZE TABLE、FORCE INDEX、系統變數調優

     編輯:MySQL 資料庫相關知識

MySQL 基於成本的優化器 (Cost-Based Optimizer)

優化器根據統計資訊估算各執行計畫成本,選擇最低成本路徑。當統計資訊不準確/缺失時,優化器可能做出次優決策。

四大診斷與干預工具

1. EXPLAIN:查看執行計畫 (核心診斷工具) ⭐


EXPLAIN SELECT * FROM t1 JOIN t2 ON t1.id = t2.id WHERE t1.status = 1;

關鍵輸出欄位解讀:

欄位關鍵值含義
typesystem/const/eq_ref/ref/range/index/ALL存取類型:const/eq_ref 最好,ALL 最差 (全表掃描)
possible_keys索引名列表可能使用的索引
key實際使用索引實際選擇的索引 (NULL 表示無索引)
key_len位元組數索引鍵長度,推斷複合索引使用了幾個欄位
rows預估掃描行數越小越好,大表應 < 1% 總行數
ExtraUsing index/Using where/Using temporary/Using filesortUsing index 覆蓋索引最佳;Using filesort 需排序、效能隱憂

2. ANALYZE TABLE:更新索引統計資訊


ANALYZE TABLE t1, t2;
-- 或全部資料庫
ANALYZE TABLE db1.table1, db1.table2, db2.table3;
  • 重新掃描索引頁面,更新 cardinality (基數統計)
  • 鎖表時間短 (僅讀取鎖),可線上執行
  • 大表建議低峰期執行

3. INDEX HINT:強制/忽略索引


-- 強制使用指定索引
SELECT * FROM t1 FORCE INDEX (idx_status) WHERE status = 1;

-- 建議使用 (優化器可選擇其他)
SELECT * FROM t1 USE INDEX (idx_status) WHERE status = 1;

-- 忽略指定索引
SELECT * FROM t1 IGNORE INDEX (idx_bad) WHERE status = 1;

⚠️ 慎用 FORCE INDEX:資料分布變化可能導致強制索引反而變慢,建議配合監控定期評估。

4. 系統變數調優:影響優化器決策

變數預設調優方向說明
max_seeks_for_key18446744073709551615設為較小值 (如 1000)假設索引查找不超過 N 次,促使優化器傾向索引而非全表掃描
optimizer_switch多項開關微調特定優化規則index_merge=on,mrr=on,batched_key_access=off...
optimizer_search_depth62複雜查詢可適當減小限制優化器搜尋深度,避免過度優化耗時
optimizer_traceOFFON (除錯用)輸出優化器決策過程 JSON,極其詳細

實戰優化案例


-- 原始慢查詢
SELECT * FROM orders WHERE user_id = 12345 AND status = 'paid' ORDER BY created_at DESC LIMIT 10;

-- EXPLAIN 顯示:type=ALL, rows=5000000, Extra=Using where; Using filesort

-- 方案一:建立複合索引 (WHERE + ORDER BY)
CREATE INDEX idx_user_status_created ON orders (user_id, status, created_at DESC);

-- 方案二:若 user_id 選擇性極高,單欄索引配合 LIMIT 下推 (MySQL 5.6+)
CREATE INDEX idx_user_id ON orders (user_id);

-- 方案三:覆蓋索引 (僅查詢部分欄位)
CREATE INDEX idx_cover ON orders (user_id, status, created_at DESC, order_id, amount);
SELECT order_id, amount FROM orders WHERE user_id = 12345 AND status = 'paid' ORDER BY created_at DESC LIMIT 10;
-- Extra: Using index (無需回表)

優化器陷阱避坑指南

  • ❌ 盲目加索引:寫入效能下降、磁碟空間暴增、優化器選擇困惑
  • ❌ 永久 FORCE INDEX:資料分布變化導致效能倒退
  • ❌ 忽略統計資訊更新:大量寫入後必須 ANALYZE TABLE
  • ✅ 定期 pt-query-digest 分析慢查詢日誌
  • ✅ 建立 optimizer_trace 基準對比
  • ✅ 測試環境模擬生產資料量驗證執行計畫
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved