在日常的MYSQL優化中我們常常看到這樣一個關鍵詞:explain,例如這種:
EXPLAIN SELECT * FROM Cloud_Order WHERE money > 10;
explain是什麼呢?使用 EXPLAIN 關鍵字可以模擬優化器執行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句的。這可以幫你分析你的查詢語句或是表結構的性能瓶頸。通過explain命令可以得到:
表的讀取順序
數據讀取操作的操作類型
哪些索引可以使用
哪些索引被實際使用
表之間的引用
每張表有多少行被優化器查詢
首先讓我們來看看使用EXPLAIN輸入的結果
結果顯示輸出了結果一堆字段和對應的值,但是這些字段是什麼意思?對應的值又是什麼呢?如何通過這些字段來分析到SQL的性能並做出優化呢?別急,下面我們就一起來一一分析。
EXPLANIN字段分析
id : SELECT識別符。這是SELECT的查詢序列號
select_type:SELECT類型,可以爲以下任何一種
·SIMPLE:簡單SELECT(不使用UNION或子查詢)
·PRIMARY:最外面的SELECT
·UNION:UNION中的第二個或後面的SELECT語句
·DEPENDENT UNION:UNION中的第二個或後面的SELECT語句,取決於外面的查詢
·UNION RESULT:UNION 的結果
·SUBQUERY:子查詢中的第一個SELECT
·DEPENDENT SUBQUERY:子查詢中的第一個SELECT,取決於外面的查詢
·DERIVED:導出表的SELECT(FROM子句的子查詢)
table:顯示這一行的數據是關於哪張表的
type:這是最重要的字段之一,顯示查詢使用了何種類型。從最好到最差的連接類型爲system、const、eq_reg、ref、range、index和ALL。下面給出各種類型,按照從最佳類型到最壞類型進行排序:
·system、const:可以將查詢的變量轉爲常量. 如id=1; id爲 主鍵或唯一鍵.
·eq_ref:訪問索引,返回某單一行的數據.(通常在聯接時出現,查詢使用的索引爲主鍵或惟一鍵)
·ref:訪問索引,返回某個值的數據.(可以返回多行) 通常使用=時發生
·range:這個連接類型使用索引返回一個範圍中的行,比如使用>或<查找東西,並且該字段上建有索引時發生的情況(注:不一定好於index)
·index:以索引的順序進行全表掃描,優點是不用排序,缺點是還要全表掃描
·ALL:全表掃描,應該儘量避免
possible_keys:顯示可能應用在這張表中的索引。如果爲空,沒有可能的索引。可以爲相關的域從WHERE語句中選擇一個合適的語句
key:實際使用的索引。如果爲NULL,則沒有使用索引。MYSQL很少會選擇優化不足的索引,此時可以在SELECT語句中使用USE INDEX(index)來強制使用一個索引或者用IGNORE INDEX(index)來強制忽略索引
key_len:使用的索引的長度。在不損失精確性的情況下,長度越短越好
ref:顯示索引的哪一列被使用了,如果可能的話,是一個常數
rows:MySQL認爲必須檢索的用來返回請求數據的行數
filtered:顯示了通過條件過濾出的行數的百分比估計值。
Extra:關於MYSQL如何解析查詢的額外信息,主要有以下幾種
·Distinct:MySQL發現第1個匹配行後,停止爲當前的行組合搜索更多的行。
·range checked for each record (index map: #):MySQL沒有發現好的可以使用的索引,但發現如果來自前面的表的列值已知,可能部分索引可以使用。
·Using index:只用到索引,可以避免訪問表.
·Using tmporary:用到臨時表
·Using where:使用到where來過慮數據. 不是所有的where clause都要顯示using where. 如以=方式訪問索引.
·Using filesort:MySQL需要額外的一次傳遞,以找出如何按排序順序檢索行。
explain實踐
說了這麼多,實踐才能出真知。下面我們通過一個簡單的例子來優化我們一些不堪的SQL。
首先我們還是一張數據表舉例。表結構如下。
這是一張典型的訂單表,其他字段我們可以省略不看,我們可以只看一個money字段,這基本是訂單表都會用到的字段。由於時間關係,事先我已經爲這個表準備了一堆模擬數據。
從上圖可以看出,表中已經有一萬條數據,下面我們來寫一個根據money條件來查詢訂單的SQL。
只能說上圖的結果不盡人意。讓我們回到之前explain字段的分析,其中type字段的值是ALL,按照分析來說,這個表用了全表搜索,我們應儘量避免!!!再看rows字段,值是16242,天啊!!所有記錄都去請求了,那慢是有原因的。
好了,通過上面的數據分析,我們可以去想一下,money字段是否能加上索引來提升查詢速度呢?因爲上述結果中好像是沒用到索引的。話不多說,我們來爲money字段加上索引
加上索引之後,我們再用剛剛的EXPLAIN語句執行一下,見證奇蹟的時候到了!
經過加上索引之後,相同的sql語句,得出的結果完全不一樣,type字段變成了range,我們也看到key顯示了money,證明了索引值被用上了。更重要的是rows字段變成了785,跟原來相比少了不知道多少,可想而知性能有了多大的提高!
好了,上面就是explain的簡單實踐。
總結
通過explain,我們可以對原有的sql做進行不同的分析,可以分析出有沒有使用到索引,可以知道這是一條快SQL還是慢SQL,EXPLAIN的作用就是幫我們顯示出SQL的性能瓶頸和各項可能的結果,這對於我們去優化MSQL的查詢有着重要的意義,根絕EXPALIN字段返回不同的結果,我們就能對原有的慢SQL進行改造了。