1. 程式人生 > >MySQL執行計劃

MySQL執行計劃

result 序列號 轉換 mea com wow pos stmt exp

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

而不是SELECT來開始語句。 (請參見“SELECT語法”。)但是,STRAIGHT_JOIN可能會阻止使用索引,因為它會禁用半連接轉換。請參見“使用半連接轉換優化子查詢,派生表和視圖引用”。

優化器跟蹤有時可以提供與EXPLAIN的信息互補的信息。但是,優化程序跟蹤格式和內容可能會在不同版本之間發生變化。有關詳細信息,請參閱MySQL內部:跟蹤優化程序。

如果在您認為應該使用索引時遇到問題,請運行ANALYZE TABLE以更新可能影響優化程序所做選擇的表統計信息,例如key的基數。請參見“ANALYZE TABLE語法”。

註意
EXPLAIN還可用於獲取有關表中列的信息。 EXPLAIN tbl_nameDESCRIBE tbl_nameSHOW COLUMNS FROM tbl_name同義。

2. EXPLAIN輸出格式

EXPLAIN語句提供有關MySQL如何執行語句的信息。 EXPLAIN適用於SELECTDELETEINSERTREPLACE和UPDATE語句。

EXPLAIN為SELECT語句中使用的每個表返回一行信息。 它按照MySQL在處理語句時讀取它們的順序列出輸出中的表。 MySQL使用嵌套循環連接方法解析所有連接。 這意味著MySQL從第一個表中讀取一行,然後在第二個表,第三個表中找到匹配的行,依此類推。 處理完所有表後,MySQL會通過表列表輸出所選列和回溯,直到找到有更多匹配行的表。 從該表中讀取下一行,並繼續下一個表。

EXPLAIN輸出包括分區信息。 此外,對於SELECT語句,EXPLAIN生成擴展信息,可以使用EXPLAIN後的SHOW WARNINGS顯示.

【註意】
在較舊的MySQL版本中,使用EXPLAIN PARTITIONSEXPLAIN 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的每個輸出行都提供有關一個表的信息。如下表:

ColumnJSON NameMeaning
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 ValueJSON NameMeaning
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 INDEXUSE INDEXIGNORE INDEX。請參考“索引hint”。
    • 對於MyISAM表,運行ANALYZE TABLE可幫助優化器選擇更好的索引。對於MyISAM表,myisamchk --analyze也是如此。
  • key_len (JSON name: key_length)

MySQL執行計劃