一個常見的理解錯誤: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使用一個外部索引排序,而不是按索引的順序讀取表。