對 EXPLAIN 史上最詳細的解析

當我們在做優化或者遇到慢查詢時,要查看sql的執行情況,我們可以使用 explan 來進行分析

y最初優化的方向就是是否存在慢查詢,如果存在我們應該怎麼去優化這些SQL語句,今天我們就介紹一下日常中經常使用的EXPLAIN命令。

EXPLAIN命令簡介

EXPLAIN命令可以模擬優化器執行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句的。分析你的查詢語句或是表結構的性能瓶頸。

通過EXPLAIN我們可以分析出以下幾個結果:

  1. 表的讀取順序;

  2. 數據讀取操作的操作類型;

  3. 哪些索引可以使用;

  4. 哪些索引被實際使用;

  5. 表之間的引用;

  6. 每張表有多少行被優化器查詢

EXPLAIN的使用方式:EXPLAIN + SQL語句,例如:

  •  
EXPLAIN SELECT * FROM t1

執行結果包含的信息,如下圖:

執行計劃返回有10個字段,分別是:id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra,下面我們就具體分析執行結果中返回的每個字段的具體含義。

EXPLAIN執行計劃字段含義詳解

ID字段

ID字段是SELECT查詢的序列號,表示查詢中執行select子句或操作表的順序;

ID字段大概可以出現3種不同的情況:

1、ID字段數值都相同,如下圖:

此時所有的ID字段數值都相同,SQL語句執行順序由上到下,順序執行。SQL中不存在子查詢等,如下SQL:

  •  
SELECT * FROM a , b WHERE a.id = b.id

2、ID字段數值按遞增順序出現,如下圖:

此時ID字段的數值是遞增出現的,ID數值越大優先級就越高,SQL語句就優先執行,對應的SQL語句如下:

  •  
SELECT * FROM a WHERE a.id = (SELECT id FROM b WHERE b.id = (SELECT id FROM c where c.sub_id = 1))

子查詢級別越深,ID的數值就越大,也就優先執行。

3、ID字段中相同數值和不相同數值同時存在,如下圖:

此時ID數值相同的算作一組,級別相同按順序執行,ID數值越高的級別越高,越先執行。

注意:衍生出來的表定義爲DERIVED,有多個時會在“DERIVED”後加入一個數字標識區分。

此種情況對應的SQL,如下:

  •  
  •  
  •  
  •  
  •  
SELECT *FROM (  SELECT a.id,a.sub FROM a) b INNER JOIN c ON c.id = b.id

select_type字段

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

table字段

table字段指的是當前執行的表

type字段

type字段是比較重要的,平常我們進行優化時主要關注的也是這個字段,這個字段表示的是我們在查詢時訪問表的方式,大概分ALL、index、range、 ref、eq_ref、const、system、NULL(從左到右,性能從差到好。一般來說,得保證查詢至少達到range級別,最好能達到ref)。

幾種類型簡介:

  • ALL:Full Table Scan, MySQL將遍歷全表以找到匹配的行

  • index: Full Index Scan,index與ALL區別爲index類型只遍歷索引樹

  • range:只檢索給定範圍的行,使用一個索引來選擇行

  • ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

  • eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作爲關聯條件

  • const、system: 當MySQL對查詢某部分進行優化,並轉換爲一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換爲一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

  • NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裏選取最小值可以通過單獨索引查找完成。

possible_keys 和 key字段

  • possible_keys:顯示可能應用在這張表中的索引,一個或多個。查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢實際使用。

  • key:實際使用的索引,如果爲NULL,則沒有使用索引。(可能原因包括沒有建立索引或索引失效) ;查詢中若使用了覆蓋索引(select 後要查詢的字段剛好和創建的索引字段完全相同),則該索引僅出現在key列表中

key_len字段

表示索引中使用的字節數,可通過該列計算查詢中使用的索引的長度,在不損失精確性的情況下,長度越短越好。key_len顯示的值爲索引字段的最大可能長度,並非實際使用長度,即key_len是根據表定義計算而得,不是通過表內檢索出的。

注意:不損失精確性的情況下,長度越短越好

ref字段

顯示索引的那一列被使用了,如果可能的話,最好是一個常數。哪些列或常量被用於查找索引列上的值。

rows字段

根據表統計信息及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數,也就是說,用的越少越好。

Extra字段

該列包含MySQL解決查詢的詳細信息,有以下幾種情況:

  1. Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據,這發生在對錶的全部的請求列都是同一個索引的部分的時候,表示mysql服務器將在存儲引擎檢索行後再進行過濾

  2. Using temporary:表示MySQL需要使用臨時表來存儲結果集,常見於排序和分組查詢,常見 group by ; order by

  3. Using filesort:當Query中包含 order by 操作,而且無法利用索引完成的排序操作稱爲“文件排序”

  4. Using join buffer:改值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。如果出現了這個值,那應該注意,根據查詢的具體情況可能需要添加索引來改進能。

  5. Impossible where:這個值強調了where語句會導致沒有符合條件的行(通過收集統計信息不可能存在結果)。

  6. Select tables optimized away:這個值意味着僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

  7. No tables used:Query語句中使用from dual 或不含任何from子句

總結

雖然EXPLAIN很簡單,但是對於優化SQL還是很有幫助的,當然如果數據量特別大的時候,我們需要另外想別的方法進行優化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章