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

MySQL 的 EXPLAIN 命令能夠查看SELECT語句的執行的計劃,是 MySQL 查詢優化的必備工具。sql

經過執行計劃能夠了解查詢方式、索引使用狀況、須要掃描的數據量以及是否須要臨時表或排序操做等信息。數據庫

咱們須要分析執行計劃對查詢進行有的放矢的優化。緩存

須要注意:服務器

  • 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 的行數爲查詢涉及的表數, 結果各列的含義爲:post

  • 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 中的子查詢

下面給出幾個示例:ui

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:code

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 index condition: 索引條件推送(MySQL 5.6 新特性),服務器層將不能直接使用索引的查詢條件推送給存儲引擎,從而避免在服務器層進行過濾。
  • using where: 服務器層對存儲引擎返回的數據進行了過濾
  • distinct: 優化distinct操做,查詢到匹配的數據後中止繼續搜索
相關文章
相關標籤/搜索