1. 程式人生 > >MySQL EXPLAIN 一: 輸出格式詳解

MySQL EXPLAIN 一: 輸出格式詳解

本文詳細介紹 MySQL 資料庫的 EXPLAIN 語句,旨在幫助 MySQL 開發人員更好的通過 EXPLAIN 語句分析 Sql 語句的執行計劃。如有不正之處,歡迎批評指正。

為了保證內容的權威性,我選擇了翻譯 Mysql5.7 官方文件8.8.2 EXPLAIN Output Format 章節的內容。

翻譯內容如下:

8.8.2 EXPLAIN 資料格式

EXPLAIN 語句提供關於 MySQL 執行語句的資訊。它同 SELECT、DELETE、INSERT、REPLACE、UPDATE語句一起使用,如:EXPLAIN SELECT * FROM TABLE。

EXPLAIN 為 SELECT 語句中使用到的每個表返回一行資訊。它在輸出中按照MySQL在處理語句時讀取它們的順序列出這些表。MySQL 使用 nested-loop join 解析所有的連線(joins)。這意味著 MySQL 從第一個表中讀取一行記錄,然後在第二個表、第三個表查詢匹配行,以此類推。當所有的表被處理完成後, MySQL 輸出選中的列,並且通過表資料(the table list)回溯有更多匹配行的表。從這個表中讀取下一行資料,繼續通過後續表進行行匹配。

EXPLAIN 語句的輸出包括分割槽資訊。同時,EXPLAIN 語句為 SELECT 語句生成擴充套件資訊,並且隨著 EXPLAIN 的SHOW WARNINGS 一起顯示(見8.8.3 Extended EXPLAIN Output Format)。

注意

在舊的 MySQL 版本中,分割槽和擴充套件資訊是通過 EXPLAIN PARTITIONSEXPLAIN EXTENDED 語句生成的。為了向後的相容性,這些語法還有可以使用的,但是現在分割槽和擴充套件資訊的輸出在預設情況下是啟用的,所以 PARTITIONS 和 EXTENDED 關鍵詞是多餘的、不被推薦的。使用它們會導致一個警告,並且在 MySQL 將來的發行版本中,它們將要被從 EXPLAIN 語法中移除。

EXPLAIN 輸出列

這個章節描述 EXPLAIN 語句生成的輸出列。之後的章節提供 type 和 Extra 列的附加資訊。

EXPLAIN 語句的每個輸出行都提供了一個表的資訊。在 Table 8.1“EXPLAIN Output Columns”中總結了輸出行包含的值,並加以詳細的說明。表(Table 8.1)的第一列顯示列名,第二列提供了等效的 JSON 屬性名稱,在輸出格式為 JSON 時使用。

Table 8.1 EXPLAIN Output Columns

Column JSON Name 含義
id select_id select 識別符號
select_type None select 型別
table table_name 輸出行描述的表的表名
partitions partitions 匹配的分割槽
type access_type 連線型別
possible_keys possible_keys 可供選擇使用的索引
key key 實際使用的索引
key_len key_length 實際使用的索引的長度
ref ref 與索引進行比較的列,也就是關聯表使用的列
rows rows 將要被檢查的估算的行數
filtered filtered 被表條件過濾的行數的百分比
Extra None 附件資訊

注意

如果 JSON 屬性的值為 NULL ,在 JSON-formatted 格式的 EXPLAIN 輸出中將不被顯示。

  • id (JSON name: select_id)
    SELECT 識別符號,該值為 SELECT 在查詢中的順序號,如果當前行引用的是其他行的聯合查詢結果,該值將被設定為 NULL。在這種情況下,表中的列將顯示一個類似於<union M,N>的值,標識該行為 id 值為 M 和 N 的聯合。

  • select_type (JSON name: none)
    SELECT 的型別,它可以是下表中展示的任意一個值。如果該值為 SIMPLE 或者 PRIMARY,一個 JSON 格式的 EXPLAIN 將以一個 query_block 的屬性顯示 SELECT 的型別。JSON 的名稱如下表所示。

select_type Value JSON Name 含義
SIMPLE None 簡單的 SELECT (沒有使用 UNION 或者 subqueries)
PRIMARY None 最外層的 SELECT
UNION None 在 UNION 查詢中的第二個或者之後的 SELECT 語句
DEPENDENT UNION dependent (true) 在 UNION 查詢中的第二個或者之後的 SELECT 語句,依賴外層的查詢
UNION RESULT union_result 聯合查詢的結果
SUBQUERY None 在子查詢中的第一個 SELECT
DEPENDENT SUBQUERY dependent (true) 在 subquery (子查詢)中的第一個 SELECT,依賴於外層查詢
DERIVED None 衍生的表 SELECT(由 FROM 中的 subquery 引起)
MATERIALIZED materialized_from_subquery 物化子查詢
UNCACHEABLE SUBQUERY cacheable (false) 子查詢的結果不能被快取,必須重新評估外部查詢的每一行
UNCACHEABLE UNION cacheable (false) 在 UNION(聯合查詢)中的第二個或者之後的多個 select 都屬於不可快取的子查詢(見 UNCACHEABLE SUBQUERY)

相關子查詢的評估不同於不可快取的子查詢評估。關於相關子查詢,子查詢只重新評估一次外部上下文環境的每一組變數的不同值。關於不可快取的子查詢,子查詢重新評估外部上下文環境的每一行資料。

子查詢的快取不同與 query cache 中查詢結果的快取(見 Section 8.10.3.1, “How the Query Cache Operates”)。子查詢快取發生在查詢執行期間,而 query cache 用來儲存查詢執行完成後的結果。

當你為 EXPLAIN 指定了 JSON 格式,它的輸出中沒有單一的屬性直接等同於 select_type,query_block 屬性對應一個給定的 SELECT。它的屬性等同於大多數的 SELECT 子查詢型別,並且只顯示可用的(例如 materialized_from_subquery),並在適當的時候進行顯示。JSON 屬性中沒有與 SIMPLE 或者 PRIMARY等同的屬性。

對於 non-SELECT 語句,select_type 顯示受影響的表的語句的型別。例如:對於 DELETE 語句,select_type 的值為 DELETE。

  • table (JSON name: table_name)
    輸出的行所指向的表的名稱,可以是下列值之一:
    • <union M,N>:該行指的是 ID 值為 M 和 N 的行的聯合。
    • <derived N>:該行指的是衍生表結果,該結果為 ID 值為 N 的行。可能會生成一個衍生表,例如:在 FROM 語句中存在一個 from a subquery。
  • type (JSON name: access_type)
    連線型別。不同型別的描述見EXPLAIN Join Types
  • possible_keys (JSON name: possible_keys)
    MySQL 可以選擇 possible_keys 列指示的索引查詢表中的行資料。注意,possible_keys 列完全獨立於 EXPLAIN 輸出中顯示的表的順序。這意味著 possible_keys 列中的一些 key 可能無法使用在實踐中生成的表的順序。
    如果該列的值是 NULL(或未定義JSON格式輸出),說明表裡沒有相關的索引。在這種情況下,您可以通過檢查 WHERE 子句來檢查其是否引用一些列或合適的包含索引的列,從而提高查詢的效能。如果是這樣的話,建立一個和適當的索引並且通過 EXPLAIN 再次檢查查詢語句,見 Section 13.1.8, “ALTER TABLE Syntax”
    使用 SHOW INDEX FROM tbl_name 語句查看錶(tbl_name )中已有的索引。
  • key (JSON name: key)
    key 列表明 MySQL 實際決定使用的索引。如果 MySQL 決定通過 possible_keys 中的某個索引查詢行,那個索引被列在 key 列中。
    key 可以命名一個不包含在 possible_keys 列中的索引。這可能發生在 possible_keys 中沒有為查詢行資料找到合適的索引,但是所有被查詢選擇的列可能包含其他的索引列。也就是說,命名的索引覆蓋了選中的列,因此儘管它不用於確定要檢索的行,但是索引掃描比資料行掃描更有效。
    關於 InnoDB儲存引擎,即使要查詢一個主鍵,次要索引可能會 cover (覆蓋)選中的列,這是因為 InnoDB 使用每個次要索引儲存主鍵值。如果 key 值為 NULL,表明 MySQL 沒有找到執行高效查詢的索引。
    可以在你的查詢語句中使用 FORCE INDEX、USE INDEX、IGNORE INDEX,強制 MySQL 使用或者忽略 possible_keys 列中的索引。見 Section 8.9.4, “Index Hints”
    關於 MyISAM 儲存引擎,執行 ANALYZE TABLE 幫助優化器選擇更好的索引。myisamchk –analyze 可以做到與 ANALYZE TABLE 一樣的效果。見 Section 13.7.2.1, “ANALYZE TABLE Syntax”
  • key_len (JSON name: key_length) 和 Section 7.6, “MyISAM Table Maintenance and Crash Recovery”
    key_len 列指示 MySQL 決定使用的 key 的長度。key_len 值能夠使你判定 MySQL 實際使用了 multiple-part key 中的多少個 part。如果 key 列的值為 NULL,則 key_len 列值也為 NULL。
  • ref (JSON name: ref)
    ref 列顯示列或常量,這些列或者常量與 key 列中的索引進行比較,以便從表中選擇行。
    如果 ref 的值為 func,那麼這個值通常是一些函式執行的結果。如果想要確定是哪個函式,在 EXPLAIN 的後面增加 SHOW WARNINGS 語句可以檢視擴充套件的 EXPLAIN 輸出。該函式實際上可能是一個算術運算子。
  • rows (JSON name: rows)
    這個 rows 就是MySQL 認為在執行查詢是必須進行逐行檢查的行的資料量。
    對於 InnoDB 型別的表,這個數字只是一個估計,並不總是精確的。
  • filtered (JSON name: filtered)
    這個 filtered 就是一個估算的將要被表的查詢條件過濾的 rows 的百分比。rows 顯示估算的被檢查的行的數量, rows × filtered / 100 顯示將要與前一個表進行連線的行數。
  • Extra (JSON name: none)
    這列包含關於 MySQL 如何解析查詢語句的附加資訊。該列的不同值的描述見 EXPLAIN Extra Information
    這裡沒有單獨的 JSON 屬性與 Extra 列的值進行對應;然而,本列中可能出現的值作為 JSON 屬性公開,或作為 message 屬性的文字公開。

本節的內容先翻譯到這裡,關於連線型別、擴充套件資訊、輸出解釋三部分,會在後續三篇部落格中進行翻譯。