MySQL EXPLAIN 命令: 查看查詢執行計划


MySQL 的 EXPLAIN 命令可以查看SELECT語句的執行的計划,是 MySQL 查詢優化的必備工具。

通過執行計划可以了解查詢方式、索引使用情況、需要掃描的數據量以及是否需要臨時表或排序操作等信息。

我們需要分析執行計划對查詢進行有的放矢的優化。

需要注意:

  • EXPLAIN不考慮觸發器、存儲過程或用戶自定義函數對查詢的影響
  • EXPLAIN不考慮緩存
  • EXPLAIN只能分析執行計划,不能顯示存儲引擎在執行查詢過程中進行的操作
  • 部分統計信息是估算的,並非精確值

本文基於 MySQL 5.6 版本。

EXPLAIN SELECT * FROM `user`
  JOIN `post` ON `user`.id = `post`.uid
WHERE user.`created_at` < '2018-10-01 00:00:00' AND `post`.status = 1;

結果:

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE user range PRIMARY,idx_created_at idx_created_at 7 null 19440 Using index condition; Using where; Using temporary; Using filesort
1 SIMPLE post ref idx_uid,idx_status idx_uid 8 user.id 1 Using where

EXPLAIN 的行數為查詢涉及的表數, 結果各列的含義為:

  • id: 查詢的唯一標識
  • select_type: 查詢的類型
  • table: 查詢的表, 可能是數據庫中的表/視圖,也可能是 FROM 中的子查詢
  • type: 搜索數據的方法
  • possible_keys: 可能使用的索引
  • key: 最終決定要使用的key
  • key_len: 查詢索引使用的字節數。通常越少越好
  • ref: 查詢的列或常量
  • rows: 需要掃描的行數,估計值。通常越少越好
  • extra: 額外的信息

select type

select_type 可能的值有:

  • SIMPLE: 簡單查詢,不包含子查詢和union
  • PRIMRARY: 包含子查詢時的最外層查詢; 使用union時的第一個查詢
  • UNION: 包含union的查詢中非第一個查詢
  • DEPENDENT UNION: 與 UNION 相同,但依賴外層查詢的結果
  • SUBQUERY: 子查詢
  • DEPENDENT SUBQUERY: 依賴外層查詢的子查詢
  • DERIVED: 用於 FROM 中的子查詢

下面給出幾個示例:

EXPLAIN SELECT * FROM post WHERE uid = (
  SELECT id FROM user WHERE name = "finley"
);
id select_type table
1 PRIMARY post
2 SUBQUERY user

DEPENDENT SUBQUERY:

EXPLAIN SELECT * FROM post WHERE uid = (
  SELECT id FROM user WHERE name = "finley" AND post.uid=user.id
);
id select_type table
1 PRIMARY post
2 DEPENDENT SUBQUERY user

type

type 字段描述了查詢的方式,從好到壞為:

  1. null: 不需要訪問索引和表即可完成, 示例: SELECT 1;

  2. const: 表中僅有一行匹配,在分解查詢計划時直接將其讀出作為常量使用。system 是 const 類型的特例。
    示例:SELECT id FROM user WHERE name = "hdt3213";

    id select_type table type possible_keys key key_len ref rows Extra
    1 SIMPLE user const uni_name uni_name 258 const 1 Using index

UNIQUE KEY uni_name (name) ON user

  1. eq_ref: 使用 PRIMARY KEY 或 UNIQUE KEY 進行關聯查詢。
    示例: SELECT * FROM post JOIN user ON post.uid = user.id WHERE user.gender = 'M';

    id select_type table type possible_keys key key_len ref rows Extra
    1 SIMPLE post ALL idx_uid 0 0 0 57796 null
    1 SIMPLE user eq_ref PRIMARY PRIMARY 8 post.uid 1 Using where
  2. ref: 使用允許重復的索引進行查詢
    示例: SELECT * FROM user WHERE phone='12345678901';

    id select_type table type possible_keys key key_len ref rows Extra
    1 SIMPLE user ref idx_phone idx_phone 259 const 1 Using index condition
  3. range: 使用索引進行范圍查詢:
    示例: SELECT * FROM user WHERE age>18;

    id select_type table type possible_keys key key_len ref rows Extra
    1 SIMPLE user ref idx_age idx_age 259 const 1 null
  4. index: 在索引上進行順序掃描。常見於在多列索引中未使用最左列進行查詢。
    示例: SELECT * FROM user WHERE last_name='smith'

    id select_type table type possible_keys key key_len ref rows Extra
    1 SIMPLE user ref idx_full_name idx_full_name 259 const 1 Using where
  5. all: 掃描全表,最壞的情況

extra

extra 列顯示了查詢過程中需要執行的其它操作,有些情況應盡力避免。

  • using filesort: 查詢時執行了排序操作而無法使用索引排序。雖然名稱為'file'但操作可能是在內存中執行的,取決是否有足夠的內存進行排序。
    應盡量避免這種filesort出現。
  • using temporary: 使用臨時表存儲中間結果,常見於ORDER BY和GROUP BY語句中。臨時表可能在內存中也可能在硬盤中,應盡量避免這種操作出現。
  • using index: 索引中包含查詢的所有列不需要查詢數據表(回表)。可以加快查詢速度。
  • using where: 使用了WHERE從句來限制哪些行將與下一張表匹配或者是返回給客戶端
  • using index condition: 索引條件推送(MySQL 5.6 新特性),服務器層將不能直接使用索引的查詢條件推送給存儲引擎,從而避免在服務器層進行過濾。
  • distinct: 優化distinct操作,查詢到匹配的數據后停止繼續搜索


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM