MySQL中的EXPLAIN

使用EXPLAIN加上SELECT語句能夠獲取優化器的查詢執行計劃數組

MySQL會在查詢上設置一個標記,當執行查詢時,這個標記會返回關於在執行計劃中每一步的信息,而不是執行它。它會返回一行或多行信息,一個表示一張表,顯示出執行計劃中的每一部分和執行的次序服務器

複雜的查詢如from子句中包含查詢,select列中也包含查詢,則執行順序爲,先執行外層查詢,再執行from子句中的子查詢,最後執行select列表中的子查詢優化

下面是查詢結果的一個示例(爲了方便查看作成了表格):排序

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE scores const PRIMARY PRIMARY 8 const 1  

1 row in set索引

實際上EXPLAIN後的SELECT語句的from子句包含子查詢時,MySQL會執行子查詢,再將結果放在一個臨時表中,而後完成外層查詢優化。內存

 

其實EXPLAIN只是一個近似的結果,有時甚至會相差甚遠,下面是EXPALIN的一些限制io

  一、EXPLAIN不會告訴你觸發器、存儲過程或UDF會如何影響查詢的table

  二、它並不支持存儲過程。儘管能夠手動抽取查詢並單獨地對齊進行EXPLAIN操做class

  三、它並不會告訴你MySQL在查詢執行中所作的特定優化file

  四、它並不會顯示關於查詢的執行計劃的全部信息

  五、它並不區分具備相同名字的事物,例如對內存排序和臨時文件排序都使用filesort,而且對於磁盤上和內存中的臨時表都顯示Using temporary

  六、可能會誤導。例如,對一個有着很小LIMIT的查詢顯示全索引掃描,5.1及以後的版本中EXPLAIN關於檢查的行數會顯示更精確的信息

 

EXPLAIN中的列

id列

  每一列的編號,若是有子查詢和JOIN時,會顯示多行,id按其在原始SQL語句中的順序編號

select_type列

  顯示對應行的查詢是簡單仍是複雜,複雜類型分爲三大類:簡單子查詢、所謂的派生表(在from子句中的子查詢)、UNION查詢,下面是可能的值

  SIMPLE  意味着查詢不包含子查詢和UNION

  PRIMARY  查詢中有複雜部分,最外層的查詢標記爲PRIMARY

  SUBQUERY  包含不在FROM子句中子查詢(在SELECT列表中的子查詢)

  DERIVED  表示FROM子句有SELECT子查詢,MySQL會先執行子查詢並將結果放在臨時表中

  UNION  UNION關鍵字後及之後的SELECT標記爲UNION,UNION前的查詢標記爲PRIMARY

  UNION RESULT  用來從包含UNION的匿名臨時表檢索結果的SELECT標記爲UNION RESULT

 

table列

  這一列顯示了對應行正在訪問哪一個表,從這一列從上往下能夠觀察到MySQL的關聯優化器爲查詢選擇的關聯順序。

  包含多個JOIN的SELECT,從下往上先執行JOIN中的表

  <derivedN>  FROM子句有子查詢時,N表示子查詢的id,N執行EXPLAIN輸出中的後面一行(先前引用)

  <unionid1,id2>  UNION RESULT的table列,id表示參與UNION的行的列表

 

type列

  顯示訪問類型,即MySQL決定如何查找表中的行,下面是最重要的訪問方法,依次從最差到最優

  ALL

    全表掃描,意味着MySQL必須掃描整張表,從頭至尾去找到須要的行。可是在查詢中使用了LIMIT或者在Extra列顯示Using distinct/not exists時

    type列也會顯示ALL

    index

    也是全表掃描,只是MySQL掃描表時按照索引次序掃描而不是逐行掃描。它最大的優勢是避免了排序,最大的缺點是要按索引次序讀取整個表

    (使用索引掃描來排序,每掃描一條記錄就回表查詢一次對應的行)

  range

    範圍掃描,即一個有限制的索引掃描,始於索引中的某一點,返回匹配區域內的行。比全表掃描好些,它意味着沒必要遍歷所有索引中的節點。

  ref

    這是一種索引訪問(索引查找),它返回全部匹配某個單個值的行,可能有多個符合兒條件的行。所以它是查找和掃描的混合體,此類索引訪問只有當使用

    非惟一性索引或者惟一性索引的非惟一性前綴時纔會發生。稱做ref由於索引要跟某個參考值比較,ref能夠用於使用=或<=>操做符的帶索引的列。

    ref_or_null是ref之上的一個變體,意味着MySQL必須在初次查找的結果裏進行第二次查找以找出NULL條目

  eq_ref

    使用這種索引,MySQL知道最多隻返回一條符合條件的記錄。這種訪問方法能夠在MySQL使用主鍵或者惟一性索引查找時看到。

  const,system

    當MySQL能對查詢的某部分進行優化並將其轉換成一個常量時,就會返回此訪問類型。如查找某一行的主鍵值where後的條件就是主鍵,MySQL就能把這個

    查詢轉換爲一個常量,而後就能夠高效地將表從聯接執行中移除

  NULL

    這種訪問方式意味着MySQL能在優化階段分解查詢語句,在執行階段甚至用不着再訪問表或者索引。例如從一個索引列裏選取最小值能夠經過單獨查找索引

    來完成,不須要在執行訪問表(覆蓋索引)

 

possible_keys列

  這一列顯示了查詢可使用哪些索引,這是基於查詢訪問的列和使用的比較操做符來判斷的。這個列表是在優化過程的早期建立的,所以有些羅列出來的索引可能

  對於後續優化過程是沒用的(有些索引不會使用)

 

key列

  這一列顯示了MySQL決定採用哪一個索引來優化對該表的訪問。若是該索引沒有出如今possible_keys列中,那麼MySQL選用它是出於另外的緣由——例如,它可能

  選擇了一個覆蓋索引,哪怕沒有where子句。

  possible_keys揭示了哪個索引能有助於高效的行查找,而key顯示的是優化採用哪個索引能夠最小化查詢成本

 

key_len列

  該列顯示了MySQL在索引裏使用的字節數(索引列表中定義的字節而不是實際數據佔用的)。若是MySQL正在使用的只是索引裏的某些列,那麼就能夠用這個值

  來算出具體是哪些列。MySQL5.5及以前版本只能使用索引的最左前綴(最左列的前綴)。

 

ref列

  這一列顯示了以前的表在key列記錄的索引中查找值所使用的列或常量。

 

rows列

  這列顯示了MySQL估計的爲了找到所需的行而要讀取的行數。這個數字是內嵌循環關聯計劃裏的循環數組。全部的rows列的值相乘,能夠估算出整個查詢會

  檢查的行數。

 

filtered列

  5.1新增的,在使用EXPLAIN EXTENDED時出現。顯示的是針對表裏符合某個條件(where子句或聯接條件)的記錄數的百分比所作的一個悲觀估算。將rows列

  和這個百分比相乘,就能看到MySQL估算它將和查詢計劃裏前一個表關聯的行數。

 

Extra列

  這一列包含是不適合顯示在其餘列上的額外信息。

  Using index

    表示MySQL將使用覆蓋索引,以免訪問表。

  Using where

    意味着MySQL服務器將在存儲引擎行後再進行過濾。許多where條件裏涉及索引中的列,當(而且若是)它讀取索引時,就能被存儲引擎檢驗,所以不是

    全部帶where子句的查詢都會顯示Using where,有事Using where的出現就是一個暗示:查詢可受益於不一樣的索引。

  Using temporary

    這意味着MySQL在對查詢結果排序時會使用一個臨時表

  Using filesort

    這意味着MySQL會對結果使用給一個外部索引排序,而不是按索引次序從表中讀取行。具體是在內存還

    是在磁盤上進行排序無從得知。

  Range checked for each record(index map:N)

    意味着沒有好用的索引,新的索引將在關聯的每一行上從新估算,N是顯示在possible_keys列中索引

    的位圖,而且是冗餘的

相關文章
相關標籤/搜索