【mysql】Explain
explain所有人都應該很熟悉,通過它我們可以知道SQL是如何執行的,雖然不是100%管用,但是至少大多數場景通過explain的輸出結果我們能直觀的看到執行計劃的相關信息。
早一些的版本explain還只能查看select語句,現在已經能支持delete,update,insert,replace了。
剛開始我想寫這個的時候只是因為這個東西經常性不用就忘記,寫了發現其實這個東西真的挺麻煩的,要把每個場景都整出來麻煩的很。
id
查詢編號,如果沒有子查詢或者聯合查詢的話,就只有一條,如果是聯合查詢的話,那么會出現一條id為null的記錄,并且標志查詢結果,因為union結果會放到臨時表中,所以我們看到這里的表名是<union1,2>這種格式。
select_type
關聯類型,決定訪問表的方式。
SIMPLE
簡單查詢,代表沒有子查詢或者union。
PRIMARY
如果不是簡單查詢,那么最外層查詢就會被標記成PRIMARY。
UNION&UNION RESULT
從上圖可以看出來了,包含聯合查詢,第一個被標記成了PRIMARY,union之后的查詢被標記成UNION,以及最后產生的UNION RESULT
DERIVED
用來標記出現在from里的子查詢,這個結果會放入臨時表中,也叫做派生表。
這個對于低版本的Mysql可能顯示是這樣的,高一點可能你看到的還是PRIMARY,因為被Mysql優化了。我換一個版本的Mysql和SQL執行可以驗證到這個結果。
SUBQUERY
不在from里的子查詢。
DEPENDENT
代表關聯子查詢(子查詢使用了外部查詢包含的列),和UNION,SUBQUERY組合產生不同的結果。
UNCACHEABLE
代表不能緩存的子查詢,也可以和UNION,SUBQUERY組合產生不同的結果。
MATERIALIZED
物化子查詢是Mysql對子查詢的優化,第一次執行子查詢時會將結果保存到臨時表,物化子查詢只需要執行一次。
比如上述DERIVED就是物化的一種體現,與之對應的就是DEPENDENT,每次子查詢都需要重新調用。
這個結果無法直觀的看出來,可以用FORMAT=JSON命令查看materialized_from_subquery字段。
table
顯示表名,從上述的一些圖中可以觀察到UNION_RESULT和DERIVED顯示的表名都有一些自己的命名規則。
比如UNION_RESULT產生的是<unionM,N>,DERIVED產生的是<derivedN>。
partitions
數據的分區信息,沒有分區忽略就好了。
type
關聯類型,決定通過什么方式找到每一行數據。以下按照速度由快到慢。
system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>ALL。
system&const
這通常是最快的查找方式,代表Mysql通過優化最終轉換成常量查詢,最常規的做法就是直接通過主鍵或者唯一索引查詢。
而system是const的一個特例(只有一行數據的系統表),隨便找一張系統表,就插入一條數據就可以看到system了。
eq_ref
通常通過主鍵索引或者唯一索引查詢時會看到eq_ref,它最多只返回一條數據。user_id是唯一索引,為了測試就關聯以下主鍵索引。
ref
也是通過索引查找,但是和eq_ref不同,ref可能匹配到多條符合條件的數據,比如最左前綴匹配或者不是主鍵和唯一索引。
最簡單的辦法,隨便查一個普通索引就可以看到。
fulltext
使用FULLTEXT索引
ref_or_null
和ref類似,但是還要進行一次查詢找到NULL的數據。
這相當于是對于IS NULL查詢的優化,如果表數據量太少的話,你或許能看到這里類型是全表掃描。
index_merge
索引合并是在Mysql5.1之后引入的,就像下面的一個OR查詢,按照原來的想法要么用name的索引,要么就是用age的索引,有了索引合并就不一樣了。
對于這種單表查詢(無法跨表合并)用到了多個索引的情況,每個索引都可能返回一個結果,Mysql會對結果進行取并集、交集,這就是索引合并了。
unique_subquery
按照官方文檔所說,unique_subquery只是eq_ref的一個特例,對于下圖中這種in的語句查詢會出現以提高查詢效率。
由于Mysql會對select進行優化,基本無法出現這個場景,只能用update這種語句了。
index_subquery
和unique_subquery類似,只是針對的是非唯一索引。
range
看名字就知道,范圍查詢,其實就是帶有限制條件的索引掃描。
常見的范圍查詢比如between and,>,<,like,in 都有可能出現range。
index
跟全表掃描類似,只是掃表是按照索引順序進行。
ALL
全表掃描,沒啥好說的。
possible_keys
可以使用哪些索引。
key
實際決定使用哪個索引。
key_len
索引字段的可能最大長度,不是表中實際數據使用的長度。
ref
表示key展示的索引實際使用的列或者常量。
rows
查詢數據需要讀取的行數,只是一個預估的數值,但是能很直觀的看出SQL的優劣了。
filtered
5.1版本之后新增字段,表示針對符合查詢條件的記錄數的百分比估算,用rows和filtered相乘可以計算出關聯表的行數。
Extra
解析查詢的附加額外信息,這個太多了,有興趣可以自己看官方文檔,只列舉一些常見的。
Using index
使用覆蓋索引。
Using index condition
使用索引下推,索引下推簡單來說就是加上了條件篩選,減少了回表的操作。
Using temporary
排序使用了臨時表。
Using filesort
使用外部索引文件排序,但是不能從這里看出是內存還是磁盤排序,我們只能知道更消耗性能。
Using where
where過濾,沒啥好說的。
Zero limit
除非你寫個LIMIT 0。
Using sort_union(), Using union(), sing intersect()
使用了索引合并,參看上文。
總結

作者:艾小仙人
鏈接:https://www.jianshu.com/p/32e41daed5b2
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

浙公網安備 33010602011771號