Mysql執行計劃全解,SQL優化必備技能

目錄

一、前言

二、解釋輸出列

三、EXPLAIN 內容解釋

1、id

2、select_type

3、table(table_name)

4、partitions(partitions)

5、type( access_type)

6、possible_keys( possible_keys)

7、key(JSON名:key)

8、key_len

9、ref

10、rows(rows)

11、filtered(filtered)

12、Extra 

四、連接類型說明

1、system

2、const

3、eq_ref

4、ref

5、fulltext

6、ref_or_null

7、index_merge

8、unique_subquery

9、index_subquery

10、range

11、index

12、ALL

五、結尾


一、前言

在較早的MySQL版本中,分區和擴展信息是使用 EXPLAIN PARTITIONS 和生成的 EXPLAIN EXTENDED。仍然可以識別這些語法的向後兼容性,但是默認情況下現在啓用了分區和擴展輸出,因此 PARTITIONS 和 EXTENDED 關鍵字已不再使用。使用它們會導致警告,並且EXPLAIN在將來的MySQL版本中會將其從語法中刪除。

你不能使用已棄用 PARTITIONS ,並 EXTENDED 在相同的關鍵字共同 EXPLAIN聲明。此外,這些關鍵字都不能與該 FORMAT選項一起使用 。

如果您不知道您所使用的Mysql的版本號,請輸入如下命令進行查看:

SELECT version();

注:本文以Mysql 5.7.28進行講解

二、解釋輸出列

每個輸出行 EXPLAIN 提供有關一個表的信息。

三、EXPLAIN 內容解釋

JSON名稱 含義
id select_id SELECT標識符
select_type 沒有 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 沒有 附加信息

 

 

 

 

 

 

 

 

 

 

注:JSON屬性 NULL不會顯示在JSON格式的EXPLAIN 輸出中。

1、id

SELECT標識符。這是SELECT查詢中的序號 。NULL如果該行引用其他行的並集結果,則該值爲。在這種情況下,該 table列顯示的值類似於 表明該行引用的行的並 集是和的值 。

2、select_type

類型SELECT,可以是下表中顯示的任何類型。JSON格式EXPLAINSELECT類型公開 爲a的屬性 query_block,除非它爲 SIMPLEPRIMARY。表格中還會顯示JSON名稱。

select_type值 JSON名稱 含義
SIMPLE 沒有 簡單SELECT(不使用UNION或子查詢)
PRIMARY 沒有 最外層SELECT
UNION 沒有 第二個或之後的SELECT陳訴UNION
DEPENDENT UNION dependent(true) 中的第二個或更高版本的SELECT語句UNION,取決於外部查詢
UNION RESULT union_result 的結果UNION。
SUBQUERY 沒有 首先SELECT在子查詢
DEPENDENT SUBQUERY dependent(true) 首先SELECT在子查詢中,取決於外部查詢
DERIVED 沒有 派生表
MATERIALIZED materialized_from_subquery 物化子查詢
UNCACHEABLE SUBQUERY cacheable(false) 子查詢,其結果無法緩存,必須針對外部查詢的每一行重新評估
UNCACHEABLE UNION cacheable(false) UNION屬於不可緩存子查詢的中的第二個或更高版本的選擇(請參閱參考資料UNCACHEABLE SUBQUERY)

 

 

 

 

 

 

 

 

 

 

DEPENDENT通常表示使用相關子查詢。

3、tabletable_name

輸出行所引用的表的名稱。這也可以是以下值之一:

<unionM,N>:該行指的是具有和id值的行 的 *M*並集 N

<derived*N*>:該行是指用於與該行的派生表結果id的值 N。派生表可能來自(例如)FROM子句中的子查詢 。

<subquery*N>:該行是指該行的物化子查詢的結果,其id 值爲N*。

4、partitionspartitions

查詢將從中匹配記錄的分區。該值適用NULL於未分區的表。

5、type( access_type

聯接類型。有關不同類型的描述,請參見 EXPLAIN 連接類型

6、possible_keys( possible_keys

 該possible_keys列指示MySQL可以選擇從中查找表中各行的索引。請注意,此列完全獨立於表的順序,如果輸出所示 EXPLAIN。這意味着possible_keys在實踐中,某些鍵可能無法與生成的表順序一起使用。

如果此列是NULL(或在JSON格式的輸出中未定義),則沒有相關的索引。在這種情況下,您可以通過檢查該WHERE 子句以檢查它是否引用了一些適合索引的列,從而提高查詢性能。如果是這樣,請創建一個適當的索引並EXPLAIN再次檢查查詢 。

要查看錶具有哪些索引,請使用。 SHOW INDEX FROM tbl_name

7、key(JSON名:key

key列指示MySQL實際決定使用的密鑰(索引)。如果MySQL決定使用possible_keys 索引之一來查找行,則將該索引列爲鍵值。

可能key會命名該值中不存在的索引 possible_keys。如果所有possible_keys索引都不適合查找行,但是查詢選擇的所有列都是其他索引的列,則可能發生這種情況。也就是說,命名索引覆蓋了選定的列,因此儘管不使用索引來確定要檢索的行,但索引掃描比數據行掃描更有效。

對於InnoDB,即使查詢也選擇了主鍵,輔助索引也可能覆蓋選定的列,因爲InnoDB主鍵值與每個輔助索引一起存儲。如果 keyNULL,則MySQL沒有找到可用於更有效地執行查詢的索引。

要強制MySQL使用或忽略列出的索引 possible_keys列,使用 FORCE INDEXUSE INDEXIGNORE INDEX在您的查詢。

對於MyISAM表,運行 ANALYZE TABLE有助於優化器選擇更好的索引。

8、key_len

key_len列指示MySQL決定使用的密鑰的長度。的值 key_len使您能夠確定MySQL實際使用的多部分鍵的多少部分。如果該key列顯示 NULL,則該key_len 列也顯示NULL

由於密鑰存儲格式的原因,一列可以使用的密鑰長度NULL 比一NOT NULL列大。

9、ref

ref列顯示將哪些列或常量與該key列中命名的索引進行比較,以 從表中選擇行。

如果值爲func,則使用的值是某些函數的結果。要查看哪個功能,請使用 SHOW WARNINGS以下 EXPLAIN命令查看擴展 EXPLAIN輸出。該函數實際上可能是算術運算符之類的運算符。

10、rowsrows

rows列指示MySQL認爲執行查詢必須檢查的行數。 對於InnoDB表,此數字是估計值,可能並不總是準確的。

11、filteredfiltered

filtered列指示將被表條件過濾的錶行的估計百分比。最大值爲100,這表示未過濾行。值從100減小表示過濾量增加。 rows顯示了檢查的估計行數,rows× filtered顯示了將與下表連接的行數。例如,如果 rows爲1000且 filtered爲50.00(50%),則與下表連接的行數爲1000×50%= 500。

12、Extra 

此列包含有關MySQL如何解析查詢的其他信息。

Extra列沒有對應的JSON屬性 ;但是,此列中可能出現的值顯示爲JSON屬性或該message屬性的文本。

四、連接類型說明

type列 EXPLAIN輸出介紹如何聯接表。在JSON格式的輸出中,這些作爲access_type屬性的值找到。以下列表描述了連接類型,從最佳類型到最差類型:

1、system

該表只有一行(=系統表)。這是const聯接類型的特例 。

2、const

該表最多具有一個匹配行,該行在查詢開始時讀取。因爲只有一行,所以優化器的其餘部分可以將這一行中列的值視爲常量。 const表非常快,因爲它們只能讀取一次。

const在將a PRIMARY KEY或 UNIQUEindex的所有部分與常數值進行比較時使用。在以下查詢中,*tbl_name*可以用作const 表:

SELECT * FROM tbl_name WHERE primary_key=1;

SELECT * FROM tbl_name
  WHERE primary_key_part1=1 AND primary_key_part2=2;

3、eq_ref

對於先前表中的每行組合,從此表中讀取一行。除了 system和 const類型,這是最好的聯接類型。當連接使用索引的所有部分並且索引爲a PRIMARY KEYUNIQUE NOT NULLindex時使用。

eq_ref可用於使用=運算符進行比較的索引列 。比較值可以是常量,也可以是使用在此表之前讀取的表中列的表達式。在以下示例中,MySQL可以使用 eq_ref連接進行處理 ref_table

SELECT * FROM ref_table,other_table
  WHERE ref_table.key_column=other_table.column;

SELECT * FROM ref_table,other_table
  WHERE ref_table.key_column_part1=other_table.column
  AND ref_table.key_column_part2=1;

4、ref

對於先前表中的每個行組合,將從該表中讀取具有匹配索引值的所有行。ref如果聯接僅使用鍵的最左前綴,或者如果鍵不是a PRIMARY KEY或 UNIQUE索引(換句話說,如果聯接無法根據鍵值選擇單個行),則使用。如果使用的鍵僅匹配幾行,則這是一種很好的聯接類型。

ref可以用於使用=<=> 運算符進行比較的索引列 。在以下示例中,MySQL可以使用 ref連接進行處理 ref_table

SELECT * FROM ref_table WHERE key_column=expr;

SELECT * FROM ref_table,other_table
  WHERE ref_table.key_column=other_table.column;

SELECT * FROM ref_table,other_table
  WHERE ref_table.key_column_part1=other_table.column
  AND ref_table.key_column_part2=1;

5、fulltext

使用FULLTEXT 索引執行連接。

6、ref_or_null

這種連接類型類似於 ref,但是除了MySQL會額外搜索包含NULL值的行。此連接類型優化最常用於解析子查詢。在以下示例中,MySQL可以使用 ref_or_null連接進行處理*ref_table*:

SELECT * FROM ref_table
  WHERE key_column=expr OR key_column IS NULL;

7、index_merge

此連接類型指示使用索引合併優化。在這種情況下,key輸出行中的列包含使用的索引列表,並key_len包含使用的索引 的最長鍵部分的列表。

8、unique_subquery

此類型替換 以下形式的eq_ref]某些 IN子查詢:

value IN (SELECT primary_key FROM single_table WHERE some_expr)

unique_subquery只是一個索引查找函數,它完全替代了子查詢以提高效率。

9、index_subquery

此連接類型類似於 unique_subquery。它代替IN子查詢,但適用於以下形式的子查詢中的非唯一索引:

value IN (SELECT key_column FROM single_table WHERE some_expr)

10、range

使用索引選擇行,僅檢索給定範圍內的行。的key 輸出行中的列指示使用哪個索引。將key_len包含已使用的時間最長的關鍵部分。該ref列 NULL適用於此類型。

range當一個鍵列使用任何的相比於恆定可使用 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, LIKE,或 IN()運營商:

SELECT * FROM tbl_name
  WHERE key_column = 10;

SELECT * FROM tbl_name
  WHERE key_column BETWEEN 10 and 20;

SELECT * FROM tbl_name
  WHERE key_column IN (10,20,30);

SELECT * FROM tbl_name
  WHERE key_part1 = 10 AND key_part2 IN (10,20,30);

11、index

 該index連接類型是一樣的 ALL,只是索引樹被掃描。這發生兩種方式:

當查詢僅使用屬於單個索引一部分的列時,MySQL可以使用此聯接類型。如果索引是查詢的覆蓋索引,並且可用於滿足表中所需的所有數據,則僅掃描索引樹。在這種情況下,Extra列爲 Using index。僅索引掃描通常比索引掃描更快, ALL因爲索引的大小通常小於表數據。使用對索引的讀取執行全表掃描,以按索引順序查找數據行。 Uses index沒有出現在 Extra列中。

12、ALL

對來自先前表的行的每個組合進行全表掃描。如果該表是未標記的第一個表 const,則通常不好,在其他所有情況下通常 非常糟糕。通常,可以ALL通過添加索引來避免這種情況,這些 索引允許基於早期表中的常量值或列值從表中檢索行。

五、結尾

好了,今天就分享到這裏,如果你覺得文章不錯,不妨給博主點個贊吧。

更多精彩好文:http://wjhsmart.vip

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章