MySQL執行計劃
MySQL執行計劃
-
使用EXPLAIN優化查詢
-
EXPLAIN輸出格式
-
擴展EXPLAIN輸出格式
-
獲取命名連接的執行計劃信息
-
估計查詢性能
EXPLAIN 語法 {EXPLAIN | DESCRIBE | DESC} tbl_name [col_name | wild] {EXPLAIN | DESCRIBE | DESC} [explain_type] {explainable_stmt | FOR CONNECTION connection_id} explain_type: { EXTENDED | PARTITIONS| FORMAT = format_name } format_name: { TRADITIONAL | JSON } explainable_stmt: { SELECT statement | DELETE statement | INSERT statement | REPLACE statement | UPDATE statement }
1. 使用EXPLAIN優化查詢
EXPLAIN語句提供有關MySQL如何執行語句的信息:
-
EXPLAIN適用於SELECT,DELETE,INSERT,REPLACE和UPDATE語句。
-
當EXPLAIN與可解釋的語句一起使用時,MySQL會顯示優化器中有關語句執行計劃的信息。也就是說,MySQL解釋了它將如何處理語句,包括有關表如何連接以及以何種順序連接的信息。
-
當EXPLAIN與
FOR CONNECTION connection_id
將顯示connection_id執行的語句的執行計劃。 -
對於SELECT語句,EXPLAIN會生成可以使用SHOW WARNINGS顯示的其他執行計劃信息。
-
EXPLAIN對於檢查涉及分區表的查詢很有用。
-
FORMAT選項可用於選擇輸出格式。 TRADITIONAL以表格格式顯示輸出。如果沒有顯示定義FORMAT選項,則默認值為TRADITIONAL。 JSON格式以JSON格式顯示信息。
在EXPLAIN的幫助下,可以看到應該向表添加索引的位置,以便通過使用索引查找行來更快地執行語句。還可以使用EXPLAIN來檢查優化程序是否以最佳順序連接表。要提示優化器使用與SELECT語句中命名表的順序相對應的連接順序,請使用SELECT STRAIGHT_JOIN
優化器跟蹤有時可以提供與EXPLAIN的信息互補的信息。但是,優化程序跟蹤格式和內容可能會在不同版本之間發生變化。有關詳細信息,請參閱MySQL內部:跟蹤優化程序。
如果在您認為應該使用索引時遇到問題,請運行ANALYZE TABLE以更新可能影響優化程序所做選擇的表統計信息,例如key的基數。請參見“ANALYZE TABLE語法”。
註意
EXPLAIN還可用於獲取有關表中列的信息。EXPLAIN tbl_name
與DESCRIBE tbl_name
和SHOW COLUMNS FROM tbl_name
同義。
2. EXPLAIN輸出格式
EXPLAIN語句提供有關MySQL如何執行語句的信息。 EXPLAIN適用於SELECT
,DELETE
,INSERT
,REPLAC
E和UPDATE
語句。
EXPLAIN為SELECT語句中使用的每個表返回一行信息。 它按照MySQL在處理語句時讀取它們的順序列出輸出中的表。 MySQL使用嵌套循環連接方法解析所有連接。 這意味著MySQL從第一個表中讀取一行,然後在第二個表,第三個表中找到匹配的行,依此類推。 處理完所有表後,MySQL會通過表列表輸出所選列和回溯,直到找到有更多匹配行的表。 從該表中讀取下一行,並繼續下一個表。
EXPLAIN輸出包括分區信息。 此外,對於SELECT語句,EXPLAIN生成擴展信息,可以使用EXPLAIN後的SHOW WARNINGS
顯示.
【註意】
在較舊的MySQL版本中,使用EXPLAIN PARTITIONS
和EXPLAIN EXTENDED
生成分區和擴展信息。 這些語法仍然可以向後兼容,但默認情況下現在啟用分區和擴展輸出,因此PARTITIONS和EXTENDED關鍵字是多余的並且已棄用。 它們的使用會導致警告,並且在將來的MySQL版本中它們將從EXPLAIN語法中刪除。您不能在同一個EXPLAIN語句中一起使用已棄用的PARTITIONS和EXTENDED關鍵字。 此外,這些關鍵字都不能與FORMAT選項一起使用。
-
EXPLAIN輸出列
-
EXPLAIN join 類型
-
EXPLAIN Extra 信息
-
EXPLAIN輸出解釋
2.1 EXPLAIN輸出列
mysql> explain select * from employees.t1 where t1.emp_no in (select emp_no from employees.salaries); +----+--------------+-------------+------------+--------+----------------+------------+---------+---------------------+---------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+--------------+-------------+------------+--------+----------------+------------+---------+---------------------+---------+----------+-------------+ | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 2837194 | 100.00 | Using where | | 1 | SIMPLE | <subquery2> | NULL | eq_ref | <auto_key> | <auto_key> | 4 | employees.t1.emp_no | 1 | 100.00 | NULL | | 2 | MATERIALIZED | salaries | NULL | index | PRIMARY,emp_no | emp_no | 4 | NULL | 2838426 | 100.00 | Using index | +----+--------------+-------------+------------+--------+----------------+------------+---------+---------------------+---------+----------+-------------+ 3 rows in set, 1 warning (0.00 sec)
EXPLAIN的每個輸出行都提供有關一個表的信息。如下表:
Column | JSON Name | Meaning |
---|---|---|
id | select_id | 查詢序列號 |
select_type | None | 查詢類型 |
table | table_name | 輸出行所引用的表 |
partitions | partitions | 匹配的分區 |
type | access_type | 連接使用的類型 |
possible_keys | possible_keys | 指出 MySQL 能在該表中使用哪些索引有助於查詢。如果為空,說明沒有可用的索引 |
key | key | 實際選擇的索引 |
key_len | key_length | 使用的索引的長度。在不損失精確性的情況下,長度越短越好 |
ref | ref | 顯示索引的哪一列被使用了 |
rows | rows | MYSQL 認為必須檢查的用來返回請求數據的行數 |
filtered | filtered | 按表條件過濾行的百分比 |
Extra | None | 附加信息 |
- id(JSON Name: select_id)
- MySQL Query Optimizer 選定的執行計劃中查詢的序列號。表示查詢中執行 select 子句或操作表的順序, id 值越大優先級越高,越先被執行。 id 相同,執行順序由上至下。
- select_type (JSON name: none)
- SELECT的類型,可以是下表中列出的任何類型。
select_type Value | JSON Name | Meaning |
---|---|---|
SIMPLE | None | 簡單的SELECT(不使用UNION或子查詢) |
PRIMARY | None | 最外層的SELECT |
UNION | None | UNION 中的第二個或隨後的 select 查詢, 不依賴於外部查詢的結果集 |
DEPENDENT UNION | dependent (true) | UNION中的第二個或隨後的SELECT語句,依賴於外部查詢 |
UNION RESULT | union_result | UNION 查詢的結果集 |
SUBQUERY | None | 子查詢中的第一個SELECT查詢,不依賴於外部查詢的結果集 |
DEPENDENT SUBQUERY | dependent (true) | 子查詢中的第一個SELECT,依賴於外部查詢的結果集 |
DERIVED | None | 用於 from 子句裏有子查詢的情況。 MySQL會遞歸執行這些子查詢,把結果放在臨時表裏 |
MATERIALIZED | materialized_from_subquery | 物化子查詢 |
UNCACHEABLE SUBQUERY | cacheable (false) | 結果集不能被緩存的子查詢,必須重新為外層查詢的每一行進行評估 |
UNCACHEABLE UNION | cacheable (false) | UNION 中的第二個或隨後的 select 查詢,屬於不可緩存的子查詢 |
-
DEPENDENT
通常表示使用相關子查詢。DEPENDENT SUBQUERY
評估與UNCACHEABLE SUBQUERY
評估不同。 對於DEPENDENT SUBQUERY,子查詢僅針對來自其外部上下文的變量的每組不同值重新評估一次。 對於UNCACHEABLE SUBQUERY,將為外部上下文的每一行重新評估子查詢。- 子查詢的可緩存性與查詢緩存中查詢結果的緩存不同(詳見“查詢緩存如何操作”)。 查詢執行期間發生子查詢緩存,而查詢緩存僅在查詢執行完成後用於存儲結果。使用EXPLAIN指定FORMAT = JSON時,輸出沒有直接等同於 select_type的單個屬性; query_block屬性對應於給定的SELECT。 可以使用與剛顯示的大多數SELECT子查詢類型等效的屬性(示例為MATERIALIZED的materialized_from_subquery),並在適當時顯示。 SIMPLE或PRIMARY沒有JSON等價物。
- 非SELECT語句的select_type值顯示受影響表的語句類型。 例如,對於DELETE語句,select_type是DELETE。
- table (JSON name: table_name)
輸出行引用的表的名稱。這也可以是以下值之一:<unionM,N>
:該行指的是id值為M和N的行的並集。<derivedN>
:該行引用id值為N的行的派生表結果。例如,派生表可能來自FROM子句中的子查詢。<subqueryN>
:該行引用id值為N的行的具體化子查詢的結果
- partitions (JSON name: partitions)
- 記錄將與查詢匹配的分區。對於非分區表,該值為NULL。
- type (JSON name: access_type)
- 連接類型。用於描述不同的連接類型
- possible_keys (JSON name: possible_keys)
possible_keys
指出 MySQL 能在該表中使用哪些索引有助查詢。如果為空,說明沒有可用的索引
- key (JSON name: key)
key
列表示MySQL實際決定使用的key
(索引)。如果MySQL決定使用其中一個possible_keys索引來查找行,那麽該索引將被列為key value。key
可能會命名possible_keys值中不存在的索引。如果所有possible_keys索引都不適合查找行,則會發生這種情況,但查詢選擇的所有列都是其他索引的列。也就是說,命名索引覆蓋了所選列,因此雖然它不用於確定要檢索的行,但索引掃描比數據行掃描更有效。- 對於InnoDB,即使查詢還選擇主鍵,輔助索引也可能覆蓋所選列,因為InnoDB將主鍵值與每個輔助索引一起存儲。如果key為NULL,則MySQL找不到用於更有效地執行查詢的索引。
- 要強制MySQL使用或忽略possible_keys列中列出的索引,請在查詢中使用
FORCE INDEX
,USE INDEX
或IGNORE INDEX
。請參考“索引hint”。 - 對於MyISAM表,運行ANALYZE TABLE可幫助優化器選擇更好的索引。對於MyISAM表,myisamchk --analyze也是如此。
- key_len (JSON name: key_length)
MySQL執行計劃