Mysql 之EXPLAIN詳解

在mysql得使用中,查詢效率低下,除cpu,io或硬體得限制外,作為java程式設計師我們主要關注得還是sql得優化。

    使用 EXPLAIN 檢視sql執行計劃

    它可以做什麼

   1.表得讀取順序

   2.資料讀取操作得操作型別

   3.哪些索引可以使用

   4.哪些索引被實際使用

   5.表之間得引用

   6.每張表有多少行被優化器查詢

id select_type table partitions type possible_keys key key_len ref rows filtered Extra

id:

select查詢得序列號,包含一組數字,表示查詢中執行select子句或操作表得順序

三種情況 :

1.id相同,執行順序由上至下

2.id不同,如果是子查詢,id的序號會遞增,id值越大優先順序越高,越先被執行

3.id相同不相同 id如果相同,可以認為是一組,從上往下執行

 在所有組中,id值越大,優先順序別越高,越先執行

select_type

SIMPLE PRIMARY SUBQUERY  DERIVED UNION UNION RESULT 

SIMPLE : 簡單的select查詢,查詢中不包含子查詢或者UNION
PRIMARY:查詢中若包含任務複雜的字部份,最外層查詢則被標記為,最後執行的
SUBQUERY:在select或wehere列表中包含了子查詢
DERIVED 在from列表中包含的子查詢被標記為DERIVED(衍生)MYSQL會遞迴執行這些子查詢,把結果放在臨時表中
UNION 若第二個select出現在UNION之後,則被標記為UNION;若UNION包含在from子句的子查詢中,外層select被標記為:DERIVED
UNION RESULT 從union表中獲取結果的select

table

顯示這一行的資料是關於哪張表的

PARTITIONS

用於分割槽表的EXPLAIN 

type

顯示查詢使用了何種型別
從最好到最差依次是:
sysytem>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>range>index>all
一般常見的是
sysytem>const>eq_ref>ref>range>index>all

一般來說,至少達到range級別,最好能達到ref

system  表只有一行記錄(等於系統表),這是const型別的特例,平時不會出現,這個也可以忽略不計
const    表示通過索引一次就找到了,const用於比較primary key或者unique索引.因為只匹配一行資料,所以很快,
如將主鍵置於where列表中,Mysql就能將改查詢轉換為一個常量
eq_ref   唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配.常見於主鍵或唯一索引掃描
ref     非唯一性索引掃描,返回匹配某個單獨值的所有行本質上也是一種索引訪問,它返回所有匹配某個值得行,
然而它可能會找 到多個符合條件的行,所以,他應該屬於查詢和掃描得混合體。
range   只檢索給定範圍得行,使用一個索引來選擇行.key列表顯示使用了哪個索引,一般就是在你得where語句中 
出現了between,<,>,in 等得查詢,這種範圍掃描索引掃描比全表掃描要好,因為它只需要開始於索引得某一點,而結束於零一點,不用掃描全部索引。
index   Full Index Scan ,index與All區別為index型別只遍歷索引樹,這通常比ALL快,因為
索引檔案通常比資料檔案小,也就是說雖然all和index都是讀全表,但index是從索引中讀取,而all是從硬碟中讀取
all Full Table Scan 將遍歷全表以找到匹配的行

prossible_keys

    

顯示可能應用在這張表中的索引,一個或多個,查詢設計到的欄位上若存在索引,則該索引將被列出,但不一定被查詢實際使用

   key  

       

 實際使用的索引,如果為null,則沒有使用索引;查詢中若使用了覆蓋索引,則該索引僅出現在key列表中.
如查詢一個表的組合索引欄位,該索引欄位的查詢順序和個數均和該表建立的索引一致,prossible_keys 這時為null而key確有值,這時的type為index,從索引中查詢

如表sys_job_running_infos 建立唯一主鍵索引,和index_name索引

key_len 

表示索引中使用的位元組數,可通過該列計算查詢中使用的索引的長度,在不損失精確性的情況下, 
長度越短越好,key_len顯示的值為索引欄位的最大可能長度,並非實際使用長度,即key_len是根據表定義計算而得,不是通過表內檢索值的

ref 

顯示索引的哪一列被使用了,如果可能的話,是一個常數,哪些列或常量被用於查詢索引列上的值

  如下圖中ref為const是常量

rows  

根據表統計資訊及索引使用情況,大致估算出找到所需的記錄所需要讀取的行數

filtered

5.7之後的版本預設有這個欄位,之前的版本需要使用explain extended。
這個欄位表示儲存引擎返回的資料在server層過濾後,剩下多少滿足查詢的記錄數量的比例,注意是百分比,不是具體記錄數。

Extra

    包含不在其他列又十分重要的額外資訊

Using filesort 說明mysql會對資料使用一個外部的索引排序,而不是按照表內的索引順序進行讀取,Mysql

                     中無法利用索引完成的排序操作稱為”檔案排序”    儘量優化

如下圖

Using Temporary 使用了臨時表儲存中間結果,Mysql在對查詢結果排序時使用臨時表。常見於order by

                            和分組查詢 group by 。  最是影響效率,一定優化

如下

Using index  表示相應的select操作中使用了覆蓋索引(Coving Index),直接訪問索引就足夠獲取到所需要的資料,不需要通過索引回表,效率不錯!

                      如果同時出現 Using where,表明索引被用來執行索引鍵值得查詢;

                     如果沒有同時出現Using where ,表明索引用來讀取資料而非執行查詢動作

          覆蓋索引 (Coviering Index)

                       理解方式一:就是select 得資料列只有從索引中就能夠取得,不必讀取資料行,Mysql可以利用索引返回select列表中得欄位,而不必根據索引再次讀取資料檔案,換句話說查詢列要被所建得索引覆蓋

                      理解方式二:索引是高效找到行得一個方法,但是一般資料庫也能使用索引找到一個列得資料,因此它不必讀取整個行。畢竟索引葉子節點儲存了它們索引得資料,當能通過讀取索引就可以得到想要得資料,那就不需要讀取行了,一個索引包含了(或覆蓋了)滿足查詢結果得資料就叫覆蓋索引.

                 注意:如果要使用覆蓋索引,一定要注意select列表中只取出需要得列,不可select*

                         因為如果將所有欄位一起做索引會導致索引檔案過大,查詢效能下降.

如下圖

 Using where 表明使用了where過濾,在查詢使用索引的情況下,需要回表去查詢所需的資料

using index condition查詢使用了索引,但是需要回表查詢資料

using index & using where查詢使用了索引,但是需要的資料都在索引列中能找到,所以不需要回表查詢資料

Impossible where  where子句得值總是false,不能用來獲取元組

Using join buffer  使用了連線查詢

Select tables optimized away     

                 在沒有group by 子句得情況下,基於索引優化min/max操作或者對於myisam儲存引擎優化 count(*)操作,不必等到執行階段再進行計算,查詢執行計劃生成得階段即完成優化

distinct    優化distinct操作,再找到第一匹配得元組後即停止找同樣得動作

     Extra主要關注前三個即可,其他的相對來說不是那麼常見,也沒前三個對於效能的影響大。