一個常見的理解錯誤:mysql在執行explain時不會執行sql語句,事實上如果查詢的from字段有子查詢,explain會執行子查詢。
explain只能解釋select查詢,對update,delete,insert需要重寫為select。
下面就explain的各個字段分別解釋。
1.id
當sql語句中有子查詢和關聯查詢時會顯示多列,id用於標志多列數據。
2.select_type
用於表示是簡單還是復雜的查詢,不包括子查詢和union的查詢為簡單查詢。如果查詢中有任何復雜的部分,外層查詢標記為primary。復雜查詢分為四大類(SUBQUERY,DERIVED,UNION,UNION RESULT)
(1)SUBQUERY:包含在select列表中的子查詢中的select,不在from子句中的select
(2)DERIVED:表示包含在from子句中的select。mysql會遞歸的執行並將結果放在一個臨時表中,服務器內部稱其為“派生表”
(3)UNION:在union中第二個和隨後的select被標記為union。
(4)UNION RESULT:用來在UNION產生的匿名臨時表檢索結果的select被標記為union result
綜上,select_type共有SIMPLE,PRIMARY,SUBQUERY,DERIVED,UNION,UNION RESULT 六種常見情況。
3.table
一般情況下為表名,當from子句中有子查詢或者union時,table列會變得復雜的多,在這種情況下,
mysql會創建匿名的臨時表,這種情況下,table列為**derived N**的形式,其中N時子查詢的id。
當有UNION時,UNION RESULT的table列包含一個參與UNION的id列表,形為**union1,3**
4.type
訪問類型mysql決定如何查找表中的行,從最差到最優依次如下:
(1)ALL:全表掃描,通常意味著mysql必須掃描整張表,從頭到尾去找到所需要的行。
(2)index:這和全表掃描一樣,只是mysql在掃描表示按索引次序進行而不是行,他的主要優點是避免了排序,最大的缺點是承擔按索引次數讀取整張表的開銷。如果Extra字段看到Using index,說明Mysql正在使用覆蓋索引,他比按索引次序全表掃描開銷要少得多。
(3)range:范圍掃描就是一個有限制的索引掃描,它開始於索引的某一點,返回匹配這個值域的行。這比全索引掃描要好一些,因為它用不著遍歷全部索引。顯而易見的范圍掃描時帶有between或者where>,當mysql使用索引去查找in()和or時也會顯示range。但是這兩者在性能上有很重要的差異。
(4)ref:這是一種索引訪問(索引查找),它返回所有匹配某個單個值得行,然而它可能找到多個符合條件的行,因此它是查找和掃描的混合體。此類索引的掃描只有在使用非唯一索引或者唯一索引的非唯一前綴時才發生。
(5)eq_ref:使用這種索引查找,mysql最多只返回一條記錄。這種訪問方法在使用mysql主鍵或者唯一索引查找時看到。它會將他們與某個參考值作比較。
(6)const,system 當mysql能夠從某部分進行優化將其轉換為一個常量時,它就會使用這些訪問類型。比如如下查詢:explain select id from mis_audit_comment where id = 1\G;
(7)NULL 這種訪問方式意味著Mysql能在優化階段分解查詢語句,在執行階段甚至用不著訪問表和索引。
5.possible_key
顯示查詢可以使用的索引。
6.key
顯示mysql決定使用哪個索引來優化對表的訪問。
7. key_len
mysql在索引裡使用的字節數,可以根據key_len計算出該索引正在使用哪些列。可以根據key_len查看sql語句使用聯合索引的情況。當有多列索引(audit_status,status,create_time)時,key_len為2時,表示只用了第一個為small int的索引。
8.ref
顯示table在key中選取的索引中查找值所用的列或者常量。
9.row
mysql估計為了找到所需的行而要讀取的行數。是mysql認為它要檢查的行數,而不是結果集裡的行數。
10.Extra
記錄了不適合在其他列中顯示的額外信息
(1)Using index:mysql將使用覆蓋索引,以避免訪問表。
(2)Using where:mysql服務器將在存儲引擎檢索行後再進行過濾。
(3)Using temporary:mysql在對結果排序時使用了臨時表
(4)Using filesort:表示mysql使用一個外部索引排序,而不是按索引的順序讀取表。