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

MySQL 查詢優化實戰技巧:EXPLAIN 深度解讀與索引優化指南

     編輯:MySQL 資料庫相關知識

MySQL 查詢優化核心在於「看懂執行計劃、建對索引、寫好 SQL」。本文系統講解 EXPLAIN 輸出各欄位含義、select_type 八大類型、type 訪問層級、索引優化實戰技巧與常見陷阱。

一、EXPLAIN 輸出欄位完整解讀

EXPLAIN SELECT * FROM car_info WHERE name LIKE '凱迪拉克%';
欄位含義優化關注點
id查詢序號,包含子查詢時遞增相同 id 從上到下執行,id 越大優先級越高
select_type查詢類型 (見下表)識別子查詢、UNION、衍生表等
table訪問的表 (或衍生表 )關注驅動表順序
type訪問類型:system > const > eq_ref > ref > range > index > ALL核心指標,避免 ALL/index,爭取 ref/range/const
possible_keys理論可用索引為 NULL 需建索引
key實際使用索引與預期不符用 FORCE/USE/IGNORE INDEX 干預
key_len使用索引長度 (Bytes)越短越好,檢查字符集/多欄位是否全用上
ref與索引比較的列/常數const/func/列名
rows預估掃描行數越小越好,配合 WHERE 條件下推
Extra額外資訊Using index (覆蓋) 好;Using where 普;Using temporary/Using filesort 差

二、select_type 八大類型實例

類型含義SQL 範例
SIMPLE無子查詢/UNION 的簡單查詢SELECT * FROM car_info;
PRIMARY最外層查詢SELECT * FROM (SELECT name FROM car_info) a; → 外層 id=1 PRIMARY
UNIONUNION 中第二個及之後的 SELECTSELECT ... UNION SELECT ... → 第二個 UNION
DEPENDENT UNIONUNION 中依賴外部查詢的 SELECTSELECT * FROM t1 WHERE id IN (SELECT ... UNION SELECT ...)
UNION RESULTUNION 合併結果id 為 NULL,table=
SUBQUERY子查詢中第一個 SELECTSELECT * FROM t1 WHERE id = (SELECT id FROM t2) → 子查詢 SUBQUERY
DEPENDENT SUBQUERY子查詢依賴外部查詢 (如 IN 子查詢)SELECT * FROM t1 WHERE id IN (SELECT id FROM t2) → 子查詢 DEPENDENT SUBQUERY
DERIVEDFROM 子查詢衍生表 (物化到臨時表)SELECT * FROM (SELECT * FROM t1) a → 衍生表 DERIVED

三、type 訪問類型效能階梯

ALL (全表掃描) 
  → index (全索引掃描) 
  → range (索引範圍掃描) 
  → ref (非唯一索引等值查找) 
  → eq_ref (唯一索引/主鍵等值查找) 
  → const/system (常數/系統表,最多 1 行) 
  → NULL (優化階段已得結果,無需訪問表)
  • ALL: 無索引或索引失效,全表掃描,大表災難
  • index: 掃描整棵索引樹,比 ALL 略快 (無需回表排序),但仍是全掃描
  • range: BETWEEN/IN/>//LIKE 'prefix%' 走索引範圍
  • ref: 非唯一索引等值查找,如 WHERE idx_col = 'val'
  • eq_ref: 主鍵/唯一索引等值查找,JOIN 關聯最優
  • const: 主鍵/唯一索引與常數比較,WHERE pk = 1,查詢優化為常數
  • NULL: EXPLAIN SELECT MIN(id) FROM t,優化器直接讀統計資訊

四、索引優化實戰技巧

  1. 同類型比較: 字符串比字符串、數字比數字,隱式轉換導致索引失效 (WHERE phone = 13800000000 字符串欄位傳數字 → 全表掃描)。
  2. 索引列參與運算失效: WHERE YEAR(create_time) = 2023 → 全表掃描。改寫 WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01'。
  3. LIKE 百分號前置失效: WHERE name LIKE '%abc' 無法走索引。若必須模糊前綴,考慮全文索引或反轉存儲。
  4. 數值運算優於字符串: 整數比較比字符串快 10 倍+,IPv4 用 INT UNSIGNED、狀態碼用 TINYINT。
  5. 類型選小不選大: TINYINT 夠用別用 INT,VARCHAR(20) 夠用別用 VARCHAR(255),減少 IO/記憶體/索引大小。
  6. NOT NULL + DEFAULT: 省去 NULL 判斷、索引統計更準、查詢優化器決策更優。
  7. ENUM 內部為整數: 處理速度快,但修改枚舉值需 DDL,慎用。
  8. PROCEDURE ANALYSE(): SELECT * FROM t PROCEDURE ANALYSE(16,256); 建議 ENUM 化欄位 (基數≤16、長度≤256)。
  9. OPTIMIZE TABLE: 碎片化嚴重表 (頻繁 UPDATE/DELETE 變長欄位) 定期整理,回收空間、重建索引。
  10. 慎用 BLOB/TEXT 索引: 僅支援前綴索引 (INDEX idx_content(content(100))),全文搜尋用 FULLTEXT。

五、強制索引語法

-- 強制使用
SELECT * FROM t FORCE INDEX (idx_name) WHERE name = 'abc';

-- 忽略索引
SELECT * FROM t IGNORE INDEX (idx_name) WHERE name = 'abc';

-- 建議使用
SELECT * FROM t USE INDEX (idx_name) WHERE name = 'abc';

六、避坑檢查清單

  1. EXPLAIN 顯示 type=ALL 或 type=index → 必須優化
  2. key 為 NULL 但 possible_keys 有值 → 索引未命中,檢查隱式轉換/運算/函數
  3. Extra 含 Using temporary、Using filesort → 索引順序不符合 ORDER BY/GROUP BY,調整索引欄位順序
  4. rows 極大 (百萬+) → 檢查 WHERE 條件是否下推、分區裁剪是否生效
  5. JOIN 關聯欄位類型/長度/字符集不一致 → 隱式轉換導致 ref 退化為 ALL

熟練掌握 EXPLAIN 語言,像醫生讀片子一樣診斷 SQL 健康狀態,配合索引設計原則與 SQL 改寫技巧,解決 90% 的查詢效能問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved