MySQL 的 EXPLAIN 語句及用法

永不停轉發表於2022-05-17

在MySQL中 DESCRIBE 和 EXPLAIN 語句是相同的意思。DESCRIBE 語句多用於獲取表結構,而 EXPLAIN 語句用於獲取查詢執行計劃(用於解釋MySQL如何執行查詢語句)。
通過 EXPLAIN 語句可以幫助我們發現表格的哪些欄位上需要建立索引,用於加速查詢。也可以使用 EXPLAIN 檢查優化器是否使用最優的順序來連線表。

EXPLAIN 語法如下:

{EXPLAIN | DESCRIBE | DESC}
    tbl_name [col_name | wild]

{EXPLAIN | DESCRIBE | DESC}
    [explain_type]
    {explainable_stmt | FOR CONNECTION connection_id}

{EXPLAIN | DESCRIBE | DESC} ANALYZE [FORMAT = TREE] select_statement

explain_type: {
    FORMAT = format_name
}

format_name: {
    TRADITIONAL
  | JSON
  | TREE
}

explainable_stmt: {
    SELECT statement
  | TABLE statement
  | DELETE statement
  | INSERT statement
  | REPLACE statement
  | UPDATE statement
}
  1. 獲取表結構

DESCRIBE 是 SHOW COLUMNS 的快捷方式,也可以用於顯示View 的資訊,SHOW COLUMNS提供了更多的列資訊。
SHOW CREATE TABLE, SHOW TABLE STATUS, SHOW INDEX 也用於提供表資訊。
DESCRIBE 預設顯示所有列的資訊,如果指定了 col_name 將只顯示該列的資訊。wild 用於指定模式串,可以使用SQL萬用字元 % 和 _。如果指定了 wild ,將顯示與模式串匹配的列資訊。如果沒有特殊字元(空格或其它特殊字元),模式串不需要使用引號括起來。

DESCRIBE City;
# 等同於
SHOW COLUMNS FROM City;
  1. 獲取執行計劃資訊
  • DESCRIBE 可以查詢 SELECT, DELETE, INSERT, REPLACE, UPDATE 的執行資訊。MySQL 8.0.19 也可以查詢 TABLE 語句。
  • MySQL從優化器獲取可解釋語句的執行計劃資訊,包括參與的表、順序等資訊。
  • 如果使用FOR CONNECTION connection_id語句,MySQL顯示該命名連線的執行計劃。
  • EXPLAIN 語句產生的執行計劃資訊可以通過 SHOW WARNINGS 顯示。
  • FORMAT 選項用於指定輸出格式,TRADITIONAL 是預設的輸出格式,以表格形式顯示。

EXPLAIN 需要的許可權與被執行解釋語句的許可權相同,解釋 view 語句時需要 SHOW VIEW 許可權,EXPLAIN ... FOR CONNECTION需要 PROCESS 許可權。
可以使用 SELECT STRAIGHT_JOIN 來告訴優化器使用 SELECT 指定的連線順序。

  1. 使用 EXPLAIN ANALYZE 獲取資訊

MySQL 8.0.18 推薦使用 EXPLAIN ANALYZE,該語句可以輸出語句的執行時間和以下資訊

  • 預計執行時間
  • 預計返回的行數
  • 返回第一行的時間
  • 迭代器的執行時間,單位毫秒
  • 迭代器返回的行數
  • 執行迴圈的次數

查詢資訊以 TREE 的形式輸出,每個節點代表一個迭代器。EXPLAIN ANALYZE 可以用於 SELECT 語句,以及多表的 UPDATE 和 DELETE 語句,MySQL 8.0.19 以後也可以用於 TABLE 語句。EXPLAIN ANALYZE 不能使用 FOR CONNECTION 。
MySQL 8.0.20 以後可以通過 KILL QUERY 或 CTRL-C 終止該語句的執行。

mysql> EXPLAIN ANALYZE SELECT * FROM t1 JOIN t2 ON (t1.c1 = t2.c2)\G
*************************** 1. row ***************************
EXPLAIN: -> Inner hash join (t2.c2 = t1.c1)  (cost=4.70 rows=6)
(actual time=0.032..0.035 rows=6 loops=1)
   -> Table scan on t2  (cost=0.06 rows=6)
(actual time=0.003..0.005 rows=6 loops=1)
   -> Hash
       -> Table scan on t1  (cost=0.85 rows=6)
(actual time=0.018..0.022 rows=6 loops=1)

mysql> EXPLAIN ANALYZE SELECT * FROM t3 WHERE i > 8\G
*************************** 1. row ***************************
EXPLAIN: -> Filter: (t3.i > 8)  (cost=1.75 rows=5)
(actual time=0.019..0.021 rows=6 loops=1)
   -> Table scan on t3  (cost=1.75 rows=15)
(actual time=0.017..0.019 rows=15 loops=1)

mysql> EXPLAIN ANALYZE SELECT * FROM t3 WHERE pk > 17\G
*************************** 1. row ***************************
EXPLAIN: -> Filter: (t3.pk > 17)  (cost=1.26 rows=5)
(actual time=0.013..0.016 rows=5 loops=1)
   -> Index range scan on t3 using PRIMARY  (cost=1.26 rows=5)
(actual time=0.012..0.014 rows=5 loops=1)

相關文章