在mysql數據庫中爲咱們提供了explain方法能夠經過它來幫助咱們分析咱們的sql語句。 登陸mysql後,具體使用以下這裏的了例子都以上篇博客中安裝的實例數據庫sakila爲例: explain select * from customer;
經過執行結果,咱們看到了explain執行後所包括的內容。每一項表明的具體含義以下:
更加詳細的參數及使用說明請參見:
mysql explain用法和結果的含義html
select_type:select語句的類型,主要包括mysql
SIMPLE:簡單SELECT(不使用UNION或子查詢) PRIMARY:最外面的SELECT UNION:UNION中的第二個或後面的SELECT語句 DEPENDENT UNION:UNION中的第二個或後面的SELECT語句,取決於外面的查詢 UNION RESULT:UNION 的結果 SUBQUERY:子查詢中的第一個SELECT DEPENDENT SUBQUERY:子查詢中的第一個SELECT,取決於外面的查詢 DERIVED:導出表的SELECT(FROM子句的子查詢)
table:查詢的表算法
possible_keys:指出MySQL能使用哪一個索引在該表中找到行sql
key:顯示MySQL實際決定使用的鍵(索引)。若是沒有選擇索引,鍵是NULL key_len:使用索引的長度
type:聯接類型。這個參數很重要。下面給出比較經常使用的幾種鏈接類型:數據庫
const:常數查找,如:主鍵,惟一索引,會很快,由於它們只讀取一次! eq_ref:對於每一個來自於前面的表的行組合,從該表中讀取一行。這多是最好的聯接類型,除了const類型。 ref:基於鏈接的查找 range:基於索引的範圍查找 index:基於索引的掃描。該聯接類型與ALL相同,除了只有索引樹被掃描。這一般比ALL快,由於索引文件一般比數據文件小。 ALL:對於每一個來自於先前的表的行組合,進行完整的表掃描。
rows: :掃描的行
extra :該列包含MySQL解決查詢的詳細信息,這個參數也很重要,主要狀況有:函數
Distinct:MySQL發現第1個匹配行後,中止爲當前的行組合搜索更多的行。 Not exists:MySQL可以對查詢進行LEFT JOIN優化,發現1個匹配LEFT JOIN標準的行後,再也不爲前面的的行組合在該表內檢查更多的行。 range checked for each record (index map: #):MySQL沒有發現好的可使用的索引,但發現若是來自前面的表的列值已知,可能部分索引可使用。 Using filesort:文件排序,須要利用額外的空間。 Using index:從只使用索引樹中的信息而不須要進一步搜索讀取實際的行來檢索表中的列信息。 Using temporary:須要用臨時表來容納結果。 Using where:WHERE 子句用於限制哪個行匹配下一個表或發送到客戶。 Using sort_union(...), Using union(...), Using intersect(...):這些函數說明如何爲index_merge聯接類型合併索引掃描。 Using index for group-by:相似於訪問表的Using index方式,Using index for group-by表示MySQL發現了一個索引, 能夠用來查 詢GROUP BY或DISTINCT查詢的全部列,而不要額外搜索硬盤訪問實際的表。
注意:性能
當咱們的執行計劃所執行的結果的extra中若是出現Using temporary或者Using filesort時,這說明咱們的sql語句就須要進行優化了。 對於Using temporary,你們並不陌生,當咱們的查詢涉及多張表時,須要將查詢結果放入第三張臨時表中來存放。這樣勢必會下降咱們的查詢效率, 因此當遇到extra中爲Using temporary時,也許就是咱們應該優化的時候了。
但針對於filesort這種狀況,咱們就沒有temporary熟悉了。它到底是什麼狀況下發生的呢? 這個 filesort 並非說經過磁盤文件進行排序,而只是告訴咱們進行了一個排序操做。即在MySQL Query Optimizer 所給出的執行計劃 (經過 EXPLAIN 命令查看)中被稱爲文件排序(filesort) 文件排序是經過相應的排序算法,將取得的數據在內存中進行排序: MySQL須要將數據在內存中進行排序, 所使用的內存區域也就是咱們經過sort_buffer_size 系統變量所設置的排序區。 這個排序區是每一個Thread 獨享的,因此說可能在同一時刻在MySQL 中可能存在多個 sort buffer 內存區域。 在MySQL中filesort 的實現算法其實是有兩種: 雙路排序:是首先根據相應的條件取出相應的排序字段和能夠直接定位行數據的行指針信息,而後在sort buffer 中進行排序。 單路排序:是一次性取出知足條件行的全部字段,而後在sort buffer中進行排序。 在MySQL4.1版本以前只有第一種排序算法雙路排序,第二種算法是從MySQL4.1開始的改進算法, 主要目的是爲了減小第一次算法中須要兩次訪問表數 據的 IO 操做,將兩次變成了一次,但相應也會耗用更多的sortbuffer 空間。 固然,MySQL4.1開始的之後全部版本同時也支持第一種算法, MySQL主要經過比較咱們所設定的系統參數 max_length_for_sort_data的大小和Query 語句所取出的字段類型大小總和來斷定須要使用哪種排序算法。 若是 max_length_for_sort_data更大,則使用第二種優化後的算法,反之使用第一種算法。因此若是但願 ORDER BY 操做的效率儘量的高, 必定要主義max_length_for_sort_data 參數的設置。曾經就有同事的數據庫出現大量的排序等待,形成系統負載很高,並且響應時間變得很長, 最後查出正是由於MySQL 使用了傳統的第一種排序算法而致使,在加大了max_length_for_sort_data 參數值以後, 系統負載立刻獲得了大的緩解,響應也快了不少。
當沒法避免排序操做時,又該如何來優化呢?很顯然,應該儘量讓 MySQL 選擇使用第二種單路算法來進行排序。 這樣能夠減小大量的隨機IO操做,很大幅度地提升排序工做的效率。
一、加大 max_length_for_sort_data 參數的設置優化
在 MySQL 中,決定使用老式排序算法仍是改進版排序算法是經過參數 max_length_for_ sort_data 來決定的。 當全部返回字段的最大長度小於這個參數值時, MySQL 就會選擇改進後的排序算法,反之,則選擇老式的算法。因此,若是有充足的內存讓MySQL 存放需要返回的非排序字段, 就能夠加大這個參數的值來讓 MySQL 選擇使用改進版的排序算法。
2.去掉沒必要要的返回字段ui
當內存不是很充裕時,不能簡單地經過強行加大上面的參數來強迫 MySQL 去使用改進版的排序算法,不然可能會形成 MySQL 不得不將數據分紅不少段, 而後進行排序,這樣可能會得不償失。此時就需要去掉沒必要要的返回字段,讓返回結果長度適應 max_length_for_sort_data 參數的限制。
三、增大 sort_buffer_size 參數設置spa
增大 sort_buffer_size 並非爲了讓 MySQL選擇改進版的排序算法,而是爲了讓MySQL儘可能減小在排序過程當中對需要排序的數據進行分段, 由於分段會形成 MySQL 不得不使用臨時表來進行交換排序。
以上就是有關explain執行計劃的一個簡單的介紹。經過查看sql語句的執行計劃,咱們能夠很容易的分析出sql語句在哪些子句或者哪些列, 返回結果等地方應該進行着重的優化,爲咱們提升程序性能帶來很大的方便!