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主要關注前三個即可,其他的相對來說不是那麼常見,也沒前三個對於效能的影響大。