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

MySQL EXPLAIN 深度解析:從輸出列含義到單表/多表優化實戰全過程

     編輯:MySQL 資料庫相關知識

EXPLAIN 是 MySQL 查詢優化器的「X 光機」,能揭示執行計劃、訪問類型、索引使用情況與潛在效能隱患。本文系統講解所有輸出列含義,並通過單表範圍查詢、左/右/內連接、三表連接四大實戰案例,演示「看計劃 → 找問題 → 加索引 → 驗證」的標準優化閉環。

EXPLAIN 輸出列完整含義

列名含義關鍵值解讀
id查詢序號值大優先執行;相同 id 從上到下
select_type查詢類型SIMPLE/PRIMARY/UNION/SUBQUERY/DEPENDENT UNION/DEPENDENT SUBQUERY/DERIVED/UNCACHEABLE...
table訪問的表衍生表顯示
type訪問類型(核心)system > const > eq_ref > ref > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL(由優到劣)
possible_keys理論可用索引NULL 表示無索引可用
key實際使用索引NULL 表示未用索引;可用 USE/FORCE/IGNORE INDEX 干預
key_len索引長度(字節)越短越好;可推斷聯合索引用了幾列
ref索引比較值來源const/列名/函數
rows預估掃描行數越小越好;統計信息不準時會偏離
Extra額外信息Using filesort(外部排序)、Using temporary(臨時表)、Using index(覆蓋索引)、Using where(WHERE 過濾)

實戰一:單表範圍查詢優化

表 article(category_id, comments, views),查詢:

SELECT author_id FROM article 
WHERE category_id=1 AND comments>1 ORDER BY views DESC LIMIT 1;

步驟 1:無索引 → type=ALL、Extra=Using filesort

type: ALL, key: NULL, rows: 3, Extra: Using where; Using filesort

步驟 2:加聯合索引 (category_id, comments, views) → type=range、filesort 仍在

ALTER TABLE article ADD INDEX x (category_id, comments, views);
type: range, key: x, key_len: 8, Extra: Using where; Using filesort

原因: comments>1 是範圍條件,導致其後 views 索引列失效(B+Tree 最左前綴原理)。

步驟 3:調整索引順序 (category_id, views) → type=ref、filesort 消失

DROP INDEX x ON article;
ALTER TABLE article ADD INDEX y (category_id, views);
type: ref, key: y, key_len: 4, Extra: Using where

範圍列放最後,等值列前置,排序列納入索引實現「索引下推 + 避免 filesort」。

實戰二:連接查詢優化(Left/Right/Inner Join)

三表 class(card)、book(card)、phone(card),各 2 萬行。

Left Join:優化右表(被驅動表)

EXPLAIN SELECT * FROM class LEFT JOIN book ON class.card=book.card;
-- 初始:雙 ALL
-- 加 book(card) 索引 → book 變 ref,rows 20000→1000
-- 加 class(card) 索引 → 無改善(左表必須全掃)

Right Join:優化左表

EXPLAIN SELECT * FROM class RIGHT JOIN book ON class.card=book.card;
-- 加 class(card) 索引 → class 變 ref
-- 加 book(card) 索引 → 無改善

Inner Join:優化任一邊均可(優化器自動選擇驅動表)

EXPLAIN SELECT * FROM class INNER JOIN book ON class.card=book.card;
-- 加 book(card) 或 class(card) 均能讓非驅動表變 ref

三表 Left Join:鏈式優化右側表

EXPLAIN SELECT * FROM class 
LEFT JOIN book ON class.card=book.card 
LEFT JOIN phone ON book.card=phone.card;
-- 給 book(card)、phone(card) 加索引 → 後兩表均為 ref,rows 大幅下降

核心優化口訣

  • 驅動表(左表/右表/小表)通常全掃,被驅動表必須有索引。
  • 範圍條件(>, <, >=, <=, LIKE '%...') 後的聯合索引列失效——調整列順序或拆分索引。
  • filesort/temporary 是效能殺手——覆蓋索引、調整 ORDER BY/GROUP BY 順序消除之。
  • key_len 讀懂聯合索引用了幾列——INT=4、BIGINT=8、VARCHAR(N)=3N+2 (utf8)。

EXPLAIN 不會說謊,但需要懂得如何提問與解讀。練就「一眼看穿執行計劃」的功力,優化從玄學變科學。

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