Explain是Mysql的自帶查詢優化器,負責select語句的優化器模塊,可以模擬優化器執行SQL查詢語句,從而知道Mysql是如何處理SQL的,語法也很簡單:Explain + SQL
以下是通過explain查詢出的幾個屬性
(常見性能瓶頸 ——
CPU:CPU飽和一般發生在數據裝入內存或從磁盤上讀取數據時
IO:磁盤I/O瓶頸發生在裝入數據遠大於內存容量時
服務器硬件的性能瓶頸:top,free,iostat,vmstat來查看系統的性能狀態)
用途:
(1)表的讀取順序,id
(2)數據讀取操作的操作類型,select_type
(3)哪些索引可以使用
(4)哪些索引被實際使用
(5)表之間的引用
(6)每張表有多少行被優化器查詢 rows
1、id:反映的是表的讀取的順序,或查詢中執行select子句的順序。
小表永遠驅動大表,三種情況:
(1)id相同,執行順序是由上至下的
(2)id不同,如果是子查詢,id序號會遞增,id值越大優先級越高,越先被執行
(3)id存在相同的,也存在不同的,所有組中,id越大越先執行,如果id相同的,從上往下順序執行
derived是衍生虛表的意思,derived2中的2對應id2
2、select_type:反映的是Mysql理解的查詢類型
(1)simple:簡單的select查詢,查詢中不包含子查詢或union。
(2)primary:查詢中若包含任何復雜的字部分,最外層查詢標記為primary。
(3)subquery:select或where列表中的子查詢。
(4)derived(衍生):在from列表中包含的子查詢,Mysql會遞歸執行這些子查詢,把結果放在臨時表里。
(5)union:若第二個select出現在union后,則被標記為union,若union包含在from字句的子查詢中,外層select將被標記為derived
(6)union result:union后的結果集
3、table:反映這一行數據是關於哪張表的
4、type:訪問類型排序
反映sql優化的狀態,至少達到range級別,最好能達到ref
查詢效率:system > const > eq_ref > ref > range > index > all
(完整的排序:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index >all)
(1)system:從單表只查出一行記錄(等於系統表),這是const類型的特例,一般不會出現
(2)const:查詢條件用到了常量,通過索引一次就找到,常在使用primary key或unique索引中出現。
where id=1寫死,所以類型是const
(3)eq_ref:唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配,常見於主鍵或唯一索引掃描。
(4)ref:非唯一性索引掃描,返回匹配某個單獨值的所有行,本質上也是一種索引訪問,它可能會找到多個符合條件的行,與eq_ref的差別是eq_ref只匹配了一條記錄。
(5)range:只檢索給定范圍的行,使用一個索引來選擇行。key列顯示使用了哪個索引,一般是在where語句中出現了between、<、>、in等的查詢。
這種范圍掃描索引掃描比全表掃描要好,因為它只需要開始於索引的某一點,而結束於另一點,不用掃描全部索引。與eq_ref和ref的區別在於篩選條件不是固定值,是范圍。
(6)index:full Index scan,index和all的區別為index類型只遍歷索引樹。這通常比all快,因為索引文件通常比數據文件小。
要獲得的id信息,剛好id在索引上,從索引中讀取
(all和index都是讀全表,但index是從索引中讀取的,而all是從硬盤中讀的)
(7)all:全表掃描,如果查詢數據量很大時,全表掃描效率是很低的。
5、possible_keys、key、key_len:反映實際用到了哪個索引,索引是否失效
(1)possible_keys:Mysql推測可能用到的索引有哪些,但不一定被查詢實際使用
(2)key:實際使用的索引,若為null,則可能沒建索引或索引失效。
(查詢中若使用了覆蓋索引,則該索引僅出現在key列表中。
覆蓋索引:select后面的字段和所建索引的個數、順序一致)
(3)key_len:表示索引中使用的字節數,可通過該列計算查詢中使用的索引的長度。同樣的查詢結果下,長度越短越好。
key_len顯示的值為索引字段的最大可能長度,並非實際使用長度,即key_len是根據表定義計算而得,不是通過表內檢索出的。
6、ref:反映哪些列或常量被用於查找索引列上的值
7、rows:根據表統計信息及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數
僅通過主鍵索引查找是641行
建完相關的復合索引再查,需要查詢的行數就變少了
8、Extra
(1)using filesort:mysql中無法利用索引完成的排序,這時會對數據使用一個外部的索引排序,而不是按照表內的索引順序進行讀取。
創建索引時就會對數據先進行排序,出現using filesort一般是因為order by后的條件導致索引失效,最好進行優化。
order by的排序最好和所建索引的順序和個數一致
(2)using temporary:使用了臨時表保存中間結果,mysql在對查詢結果排序時使用臨時表。常見於排序order by和分組查詢group by。
影響更大,所以要么不建索引,要么group by的順序要和索引一致
(3)using index:表示相應的select操作中使用了覆蓋索引,避免訪問了表的數據行,效率好
覆蓋索引:select后的數據列只從索引就能取得,不必讀取數據行,且與所建索引的個數(查詢列小於等於索引個數)、順序一致。
所以如果要用覆蓋索引,就要注意select的列只取需要用到的列,不用select *,同時如果將所有字段一起做索引會導致索引文件過大,性能會下降。
出現using where,表明索引被用來執行索引鍵值的查找
如果沒有同時出現using where,表明索引用來讀取數據而非執行查找動作。
(4)using where:表明使用了where過濾
(5)using join buffer:使用了連接緩存
(6)impossible where:where子句的值是false
(7)select tables optimized away
(8)distinct:優化distinct操作,在找到第一匹配的元組后即停止找同樣值的動作