引言:見過不少關於MySQL的查詢語句優化的文章,可是當你用過EXPLAIN後,瞭解其中的原理後,發現那些文章都太業餘了。總之一句,EXPLAIN簡直不要太好用了!mysql
EXPLAIN是MySQl必不可少的一個分析工具,主要用來測試sql語句的性能及對sql語句的優化,或者說模擬優化器執行SQL語句。sql
簡單的說是execute plan, 獲取MySQL數據庫的執行計劃。本文重點介紹explain的使用和各參數的意義。數據庫
首先看一個例子,現有一張表格filesinfo,主鍵FileId,創建索引 create index DevInfoIndex on FilesInfo (CamID, SliceStartTime, SliceStopTime);表格除DevInfoIndex顯示的字段外還有其餘幾個字段。目前表格有110左右條數據。緩存
而後咱們執行下面語句:工具
(1)性能
該SQL語句,對主鍵FileId進行排序,且只查找開始四條。而rows也是4,由於能夠看到key中直接用的主鍵索引。測試
(2)咱們再執行下一條語句:優化
和上面比較,咱們把排序改爲了索引DevInfoIndex 的第一個字段。rows仍是4,而key變化了,使用索引DevInfoIndex ,最後Extra顯示使用了索引。spa
(3)接着咱們繼續執行:blog
和上一條語句比較,咱們只是修改排序的字段,SliceStartTime是索引的第二個字段。而rows變成了53。
從Extra看,雖然查找了索引,可是還用了filesort文件排序,也就是說明聯合索引的數據先按第一個字段的順序進行存儲,後面的字段單獨須要排序查找時,須要再對文件進行排序。
(4)繼續
此次語句的變化主要是查找內容,*表示全部字段;排序字段仍是索引的首個字段CamID,但是type變成了ALL,全表掃描;因此Extra顯示filesort。
以上幾步操做只是 對explain工具顯示的結果的幾個主要參數進行分析和展現。
下面再逐一進行介紹。
id: 查詢的序列號;查詢中執行select子句或操做表的順序,id值越大優先級越高,越先被執行。id 相同,執行順序由上至下。
select_type : 查詢的類型,主要包括普通查詢、聯合查詢、子查詢。主要取值:
SIMPLE------簡單的select查詢,不使用union及子查詢.
PRIMARY------最外層的select查詢
UNION------UNION 中的第二個或隨後的select查詢,不依賴於外部查詢的結果集
DEPENDENT UNION------UNION 中的第二個或隨後的select查詢,依賴於外部查詢的結果集
SUBQUERY------子查詢中的第一個select查詢,不依賴於外 部查詢的結果集
DEPENDENT SUBQUERY------子查詢中的第一個select查詢,依賴於外部查詢的結果集
DERIVED------用於 from 子句裏有子查詢的狀況。 MySQL會遞歸執行這些子查詢, 把結果放在臨時表裏
UNCACHEABLE SUBQUERY------結果集不能被緩存的子查詢,必須從新爲外層查詢的每一行進行評估
UNCACHEABLE UNION------UNION 中的第二個或隨後的selec查詢,屬於不可緩存的子查詢
table:所訪問數據庫的表的名稱
type:聯合查詢使用的類型顯示的訪問類型是重要指標,結果從好到壞:
system------系統表;表僅有一行(=系統表)。這是const鏈接類型的一個特例。
const------讀常量;const用於用常數值比較 PRIMARY KEY 時。當查詢的表僅有一行時,使用System。
eq_ref ------最多一條匹配結果,一般是經過主鍵訪問;
ref------;鏈接不能基於關鍵字選擇單個行,可能查找 到多個符合條件的行。叫作ref是由於索引要 跟某個參考值相比較。這個參考值或者是一個常數,或者是來自一個表裏的多表查詢的結果值。
fulltext------全文索引檢索;
ref_or_null------;如同ref, 可是MySQL必須在初次查找的結果 裏找出null條目,而後進行二次查找。
index_merge------合併索引結果集;說明索引合併優化被使用了。
unique_subquery------;在某些 IN 查詢中使用此種類型,而不是常規的 ref:value IN (SELECT primary_key FROM single_table WHERE some_expr)
index_subquery()------子查詢返回的是索引,但非主鍵;在某些IN查詢中使用此種類型,與unique_subquery相似,可是查詢的是非惟一性索引:value IN (SELECT key_column FROM single_table WHERE some_expr)
range------索引範圍掃描;只檢索給定範圍的行,使用一個索引來選擇行。key列顯示使用了哪一個索引。當使用=、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操做符,用常量比較關鍵字列時,可使用range。
index------全索引掃描;全表掃描,只是掃描表的時候按照索引次序進行而不是行。主要優勢就是避免了排序, 可是開銷仍然很是大。
all------全表掃描;最壞的狀況,從頭至尾全表掃描。
possible_keys: 指出mysql能使用哪一個索引有助於在該表中找到該行,若是這個值爲空,則表示沒有相關的索引。
key:顯示mysql實際決定使用的建,若是沒有索引被選擇,鍵是null。
key_len:顯示mysql決定使用索引的長度,在不損失精確性的狀況 下,長度越短越好。若是key是空,則長度就是null。
ref:顯示哪一個字段或常數與key一塊兒使用。若是使用了索引則顯示const,不然,顯示null。
rows:MYSQL 認爲必須檢查的用來返回請求數據的行數。
Extra: 出現如下2項意味着MYSQL根本不能使用索引,效率會受到重大影響。應儘量對此進行優化。
Using filesort------表示 MySQL 會對結果使用一個外部索引排序,而不是從表裏按索引次序讀到相關內容。可能在內存或者磁盤上進行排序。
MySQL 中沒法利用索引完成的排序操做稱爲「文件排序」。
Using temporary------表示 MySQL 在對查詢結果排序時使用臨時表。常見於排序 order by 和分組查詢 group by。
以上對命令explain及其參數的意義基本介紹完成。但願之後對於SQL語句的性能分析,是否須要優化,作到心中有數。