mysql執行計劃

  文章:https://blog.csdn.net/wuseyukui/article/details/71512793的學習筆記
----------------------------------------------------------------------------------------------
  目前國內大多數互聯網公司使用的數據庫都是mysql,雖然postgresql也很是優秀,甚至在某些方面超過mysql,但不可忽視的一個問題是mysql擁有完善的技術社區,基本上生產碰到的問題都會在社區中找到相關的處理辦法。mysql畢竟不是商用數據庫,在數據量偏大以後(單表幾十萬),基本就須要開始進行優化了。
  而sql的優化,一切都是圍繞執行計劃展開的,看懂mysql的執行計劃也就顯得尤爲重要了。
  能夠看到執行計劃有不少字段,其中比較重要的爲id、type、key、rows、extra。咱們逐個看一下各個字段的含義:
一、 id,表示語句的執行優先級,數字越大優先級越高;id相同的時候,執行順序爲從上到下;
能夠看到,a,b,c三張表id都是1,表示這三個表查詢的優先級都是相同的。
而上圖,因爲有子查詢,子查詢的語句優先級較高,所以id爲2,比另外三個要高。除此之外,咱們還注意到,三張表的執行順序變了,跟子查詢條件關聯的tb_a表變成了在id爲1的狀況下優先查詢的表。這說明where條件能夠影響表的查詢順序。
二、 select_type,查詢類型;主要用於區分普通查詢、聯合查詢、子查詢等分類;
  一、 SIMPLE:簡單的select查詢,查詢中不包含子查詢或者union
  二、 PRIMARY:查詢中包含任何複雜的子部分,最外層查詢則被標記爲primary
  三、 SUBQUERY:在select 或 where列表中包含了子查詢
  四、 DERIVED:在from列表中包含的子查詢被標記爲derived(衍生),mysql或遞歸執行這些子查詢,把結果放在臨時表裏
  五、 UNION:若第二個select出如今union以後,則被標記爲union;若union包含在from子句的子查詢中,外層select將被標記爲derived
  六、 UNION RESULT:從union表獲取結果的select
  其中一、二、3能夠合起來理解,就是一個普通的查詢,好比select * from table_a,咱們叫作簡單查詢(simple)。若是有子查詢,則外層的叫主查詢(primary),內層的叫子查詢(subquery)。4的意思是臨時表的狀況,好比咱們要從一個查詢的結果集中獲取數據,再跟其它表進行join,則這個做爲臨時表跟其它表進行join操做的結果集就是派生查詢(derived,派生,衍生的意思)。5跟6的意思,下圖很明顯了,就是union以後的查詢被標記位union,最終的結果就是union result。
三、 type,訪問類型;sql優化中很重要的一個指標,從好到壞一次是:
  system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
  通常來講,好的sql查詢至少達到range級別,最好能達到ref
  一、system:表裏只有一行記錄,至關於const類型的特例,平時幾乎不會出現,能夠忽略不計;
  二、const:表示經過索引一次就找到了,const用於比較primary key或者unique索引。由於只需匹配一行數據,因此很快。若是主鍵置於where中,mysql就能將該查詢轉換爲一個const;const:常數;
  三、eq_ref: 惟一索引掃描,對於每一個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或者惟一索引。
  四、ref: 非惟一索引,返回匹配某個單獨之的全部行。本質也是一種索引訪問,它返回全部匹配某個單獨值的行,然而它也可能會找到多個符合條件的行,因此它應該屬於查找和掃描的混合體。
  五、range:只檢索給定範圍的行,使用一個索引來選擇行。key列顯示使用了那個索引。通常就是在where中出現了between、>、<、in等的查詢。這種索引列上的範圍掃描比全索引掃描要好。只須要開始於某個點,結束語某個點,不用掃描所有索引。
  六、index:全索引掃描;index與all區別是index類型只遍歷索引樹,而all爲全表掃描;二者雖然都是全表掃描,但index是從索引中讀取,而all是從硬盤讀取;
  id爲主鍵,有主鍵索引,但由於要查找全部的id,所以須要掃描所有索引,上圖走的是age_index索引,不是主鍵索引,由於此時主鍵沒有索引,若在主鍵添加惟一索引id_index,則key列會變爲id_index,表示使用的是主鍵的惟一索引;name字段沒有索引,故而掃描全表數據:
四、 possible_keys:查詢涉及到的字段上存在索引,則列出該索引,但不必定會被使用;
五、 key:真正使用的索引;
六、 key_len:表示索引中使用的字節數,能夠經過該列計算查詢中使用的索引的長度;並不是實際使用長度,即key_len是根據表定義計算而得,不是經過表內檢索出的。理論上越小越好。
七、 ref:當前表在利用key列記錄中的索引進行查詢時,用到的列或者常數。
八、 rows:查詢所涉及的表數據的行數,越小越好;
九、 extra:擴展信息,不適合在其餘字段中展現,但十分重要的額外信息;
  一、using filesort:mysql對數據使用一個外部的索引排序,而不是按照表內的索引進行排序讀取。也就是mysql沒法利用索引完成的排序操做稱爲「文件排序」;
  因爲name字段沒有索引,咱們在利用主鍵完成數據檢索後按name進行排序,這個時候mysql是不知道如何進行的,由於name沒有現成的索引排序,所以mysql內部必須再實現一次「文件排序」;
  二、using temporary:使用臨時表保存中間結果,也就是mysql在對查詢結果進行排序時使用了臨時表,常見於order by跟group by
  三、using index:表示相應的select操做中使用了覆蓋索引,避免了訪問表的數據行,效率高;
若是同時出現了using where,代表索引被用來執行索引鍵值的查找;若是沒有同時出現using where,代表索引用來讀取數據,而非進行查找動做;
  覆蓋索引:
  實際上就是數據存在了索引上,所以在查詢的時候,只須要讀取了索引也就順便拿到了數據,不須要再次經過索引中的指針去查找硬盤中的表數據。固然,這種狀況下,由於索引中包含數據,故而索引一般體積是比較大的,因此,通常來講,對於一張表,只有一個覆蓋索引,這個索引一般都是主鍵索引。想一下,若是一個表有兩個覆蓋索引,那這個表的數據不是有2份了麼,這太浪費存儲空間了。
  四、using where:使用了where過濾條件;
  五、using join buffer:使用了鏈接緩存;
  六、impossible where:where子句中的值老是false,不能用來過濾任何數據;
  七、select tables optimized away:在沒有group by子句的狀況下,基於索引優化min/max操做或者對於myisam引擎優化count(*)操做,沒必要等到執行階段再進行計算,查詢執行計劃生成的階段便可完成優化;
  八、distinct:優化distinct操做,在找到第一個匹配的數據後即中止查找一樣值的操做;
相關文章
相關標籤/搜索