MySQL 5.7 檢視理解SQL執行計劃

feelpurple發表於2016-06-01
可以使用EXPLAIN語句檢視SQL的執行計劃,執行計劃的資訊來自於最佳化器。

在MySQL 5.7,可以檢視SELECT, DELETE, INSERT, REPLACE, 和 UPDATE語句的執行計劃。

在MySQL 5.7.3,EXPLAIN EXTENDED可以獲取更詳細的執行計劃資訊,EXPLAIN PARTITIONS在獲取有分割槽表的執行計劃時很有用。

FORMAT選項可以用來選擇輸出的格式。TRADITIONAL代表以表格形式輸出,它是預設的輸出格式。JSON格式代表以JSON格式輸出,輸出結果中包含擴充套件的執行計劃資訊和分割槽表資訊。

如果索引沒有正常使用,可以透過執行ANALYZE TABLE命令來更新表的統計資訊,例如鍵值的cardinality,這會影響到最佳化器的選擇。

mysql> explain select * from emp e where e.deptno not in (select deptno from dept d);
+----+--------------------+-------+-----------------+---------------+---------+---------+------+------+-------------------------------------------------+
| id | select_type        | table | type            | possible_keys | key     | key_len | ref  | rows | Extra                                           |
+----+--------------------+-------+-----------------+---------------+---------+---------+------+------+-------------------------------------------------+
|  1 | PRIMARY            | e     | ALL             | NULL          | NULL    | NULL    | NULL |   14 | Using where                                     |
|  2 | DEPENDENT SUBQUERY | d     | unique_subquery | PRIMARY       | PRIMARY | 4       | func |    1 | Using index; Using where; Full scan on NULL key |
+----+--------------------+-------+-----------------+---------------+---------+---------+------+------+-------------------------------------------------+
2 rows in set (0.00 sec)

輸出欄位說明:

id     查詢的執行順序號
select_type     查詢型別,包括:

SIMPLE     簡單查詢(不使用UNION或子查詢)
PRIMARY     最外層的SELECT語句
UNION     在UNION結構中的第二個及以上的SELECT語句
DEPENDENT UNION      在UNION結構中的第二個及以上的SELECT語句,依賴外層查詢
UNION RESULT     UNION的結果
SUBQUERY     子查詢中的第一個SELECT語句
DEPENDENT SUBQUERY     子查詢中的第一個SELECT語句,依賴於外層查詢
DERIVED      子查詢中FROM後面的語句
MATERIALIZED     物化檢視子查詢
UNCACHEABLE SUBQUERY     查詢結果沒有被快取且需要重新外層查詢計算每行資料的子查詢
UNCACHEABLE UNION UNION    結構中第二個及之後的SELECT語句且沒有生成查詢快取

table     表名
type     表連線的型別,包括:

system     表中只有一行資料,這是cost連線型別的一種特殊情況
const     表中只有一行匹配記錄,且在查詢中被最先讀取
eq_ref     和之前的表作nested loop連線時,每次兩個表中連線欄位相比,都有一行匹配的記錄。當索引中的所有部分被用於連線且索引是主鍵索引或UNIQUE非空索引時,會使用這種型別。
ref     每次和之前的表做連線時,讀取所有符合條件的索引值。如果連線使用索引的最左邊字首欄位,或者索引不是主鍵或UNIQUE索引,會用到這種連線方式,也就是說如果連線不能基於每個符合連線條件的索引值選擇出單獨的一行,則會使用這種連線方式。
fulltext     使用FULLTEXT索引來建立連線
ref_or_null     連線型別類似ref,除此之外,MySQL會額外掃描出包含NULL值的行。這種連線方式通常用於有子查詢的情形下。
index_merge     使用索引合併的連線方式。在這種情況下,key欄位會包含使用的索引,key_len包含使用索引的最長索引部分。
unique_subquery      這種連線方式在某種情況下會代替eq_ref,如value IN (SELECT primary_key FROM single_table WHERE some_expr),這種方式使用索引查詢功能代替子查詢,以獲得更好的執行效率。
index_subquery      這種連線方式類似unique_subquery。它會代替IN子查詢,但是它適用於非unique索引的子查詢,如value IN (SELECT key_column FROM single_table WHERE some_expr)
range     使用索引掃描出指定範圍的行。key欄位指示使用的索引。key_len指示索引的最大長度。ref欄位會顯示NULL
index     這種索引連線型別和ALL相同,除了索引樹被掃描到。這會出現在兩種情況下:一、如果該索引是一個覆蓋索引查詢,且只掃描出索引樹。在這種情況下,Extra欄位會顯示Using index。二、透過索引順序來執行全表掃描。
ALL     和之前表做連線時,每次兩表關聯時都做全表掃描。

possible_keys     可供選擇的索引
key     實際選擇的索引
key_len      選擇的索引長度
ref     顯示和索引相比較的欄位或常量,如果這個欄位的值是func,這個值會用在函式的結果中。
rows     估計的表的行數
Extra     額外資訊

mysql> explain select * from buy_log where userid=2;
+----+-------------+---------+------+-----------------+--------+---------+-------+------+-------+
| id | select_type | table   | type | possible_keys   | key    | key_len | ref   | rows | Extra |
+----+-------------+---------+------+-----------------+--------+---------+-------+------+-------+
|  1 | SIMPLE      | buy_log | ref  | userid,userid_2 | userid | 4       | const |    1 | NULL  |
+----+-------------+---------+------+-----------------+--------+---------+-------+------+-------+
1 row in set (0.00 sec)

(04:14:50) [dmcdbMTNNG]> explain select count(*) from ADDSubscribers where timestamp between 1483351200 and 1483354800;
+----+-------------+----------------+-------+---------------+-----------+---------+------+---------+-----------------------------------+
| id | select_type | table          | type  | possible_keys | key       | key_len | ref  | rows    | Extra                             |
+----+-------------+----------------+-------+---------------+-----------+---------+------+---------+-----------------------------------+
|  1 | SIMPLE      | ADDSubscribers | range | Timestamp     | Timestamp | 8       | NULL | 3515427 | Using where with pushed condition |
+----+-------------+----------------+-------+---------------+-----------+---------+------+---------+-----------------------------------+
1 row in set (0.00 sec)

這個資訊只適用於NDB表。MySQL Cluster使用這個條件來提高效率。

Using where with pushed condition (JSON property: message)
This item applies to NDB tables only. It means that MySQL Cluster is using the Condition Pushdown
optimization to improve the efficiency of a direct comparison between a nonindexed column and a
constant. In such cases, the condition is “pushed down” to the cluster's data nodes and is evaluated on
all data nodes simultaneously. This eliminates the need to send nonmatching rows over the network, and
can speed up such queries by a factor of 5 to 10 times over cases where Condition Pushdown could be
but is not used. For more information, see Section 9.2.1.5, “Engine Condition Pushdown Optimization”.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26506993/viewspace-2112440/,如需轉載,請註明出處,否則將追究法律責任。

相關文章