1. 程式人生 > 資料庫 >【mysql】- Expalin篇

【mysql】- Expalin篇

簡介

  • id:在一個大的查詢語句中每個 SELECT 關鍵字都對應一個唯一的id
    • 與查詢優化器有關,假如被優化過,那麼可能是上下兩個的id都是一樣的
  • select_type:SELECT 關鍵字對應的那個查詢的型別
    • SIMPLE:SELECT (not using UNION or subqueries),語句中不包含UNION或者子查詢的查詢都算作是 SIMPLE 型別
      • 簡單查詢: SELECT * FROM s1
      • 連線查詢也算是 SIMPLE 型別:SELECT * FROM s1 INNER JOIN s2
    • PRIMARY:Outermost SELECT,對於包含 UNION 、 UNION ALL或者子查詢的大查詢來說,它是由幾個小查詢組成的,其中最左邊的那個查詢的 select_type 值就是 PRIMARY
      • 比如 SELECT * FROM s1 UNION SELECT * FROM s2
    • UNION:Second or later SELECT statement in a UNION,對於包含UNION或者UNION ALL 的大查詢來說,它是由幾個小查詢組成的,其中除了最左邊的那個小查詢以外,其餘的小查詢的 select_type 值就是 UNION
    • UNION RESULT:Result of a UNION,MySQL選擇使用臨時表來完成UNION查詢的去重工作,針對該臨時表的查詢的select_type 就是 UNION RESULT
    • SUBQUERY:First SELECT in subquery,如果包含子查詢的查詢語句不能夠轉為對應的semi-join的形式,並且該子查詢是不相關子查詢,並且查詢優化器決定採用將該子查詢物化的方案來執行該子查詢時,該子查詢的第一個 SELECT 關鍵字代表的那個查詢的 select_type 就是 SUBQUERY
      • 比如:SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2) OR key3 = 'a'
      • select_type為SUBQUERY的子查詢由於會被物化,所以只需要執行一遍
    • DEPENDENT SUBQUERY:First SELECT in subquery, dependent on outer query,如果包含子查詢的查詢語句不能夠轉為對應的semi-join的形式,並且該子查詢是相關子查詢,則該子查詢的第一個SELECT關鍵字代表的那個查詢的select_type就是DEPENDENT SUBQUERY
      • SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2 WHERE s1.key2 = s2.key2) OR key3 = 'a'
      • 注:select_type為DEPENDENT SUBQUERY的查詢可能會被執行多次
    • DEPENDENT UNION:Second or later SELECT statement in a UNION, dependent on outer query,在包含 UNION 或者UNION ALL的大查詢中,如果各個小查詢都依賴於外層查詢的話,那除了最左邊的那個小查詢之外,其餘的子查詢的 select_type 的值就是 DEPENDENT UNION
      • SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2 WHERE key1 = 'a' UNION SELECT key1 FROM s1 WHERE key1 = 'b')
    • DERIVED:Derived table,對於採用物化的方式執行的包含派生表的查詢,該派生表對應的子查詢的select_type就是DERIVED
    • MATERIALIZED:Materialized subquery,當查詢優化器在執行包含子查詢的語句時,選擇將子查詢物化之後與外層查詢進行連線查詢時,該子查詢對應的select_type 屬性就是 MATERIALIZED
      • 如:SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2)
    • UNCACHEABLE SUBQUERY:A subquery for which the result cannot be cached and must be re-evaluated for each row of the outer query,一個子查詢的結果不能被快取,必須重新評估外連結的第一行
    • UNCACHEABLE UNION:The second or later select in a UNION that belongs to an uncacheable subquery (see UNCACHEABLE SUBQUERY)
  • table:表名
  • partitions:匹配的分割槽資訊
    • 當對錶進行分割槽處理時,對於某些查詢會使用到分割槽的情況,此時會出現涉及的分割槽
  • type:針對單表的訪問方法
    • system
      • 當表中只有一條記錄並且該表使用的儲存引擎的統計資料是精確的,比如MyISAM、Memory,那麼對該表的訪問方法就是 system
    • const
      • 根據主鍵或者唯一二級索引列與常數進行等值匹配時,對單表的訪問方法就是const
    • eq_ref
      • 在連線查詢時,如果被驅動表是通過主鍵或者唯一二級索引等值匹配的方式進行訪問的(如果該主鍵或者唯一二級索引是聯合索引的話,所有的索引列都必須進行等值比較),則對該被驅動表的訪問方法就是eq_ref
    • ref
      • 當通過普通的二級索引列與常量進行等值匹配時來查詢某個表,那麼對該表的訪問方法就可能是 ref
    • fulltext
      • 全文索引,在標準的MySQL中, 只有MyISAM引擎支援全文索引。 不過在還沒有正式釋出的MySQL5.6中,InnoDB已經實驗性質地支援全文索引了
    • ref_or_null
      • 當對普通二級索引進行等值匹配查詢,該索引列的值也可以是NULL值時,那麼對該表的訪問方法就可能是 ref_or_null
    • index_merge
      • 索引合併,在某些場景下可以使用Intersection、Union、Sort-Union這三種索引合併的方式來執行查詢
    • unique_subquery
      • 類似於兩表連線中被驅動表的eq_ref訪問方法,unique_subquery是針對在某些包含IN子查詢的查詢語句中,如果查詢優化器決定將IN子查詢轉換為EXISTS子查詢,並且子查詢可以使用到主鍵進行等值匹配的話,那麼該子查詢執行計劃的 type 列的值就是 unique_subquery
    • index_subquery
      • index_subquery 與 unique_subquery 類似,只不過訪問子查詢中的表時使用的是普通的索引
    • range
      • 如果使用索引獲取某些範圍區間的記錄,那麼就可能使用到range訪問方法
    • index
      • 當我們可以使用索引覆蓋,但需要掃描全部的索引記錄時,該表的訪問方法就是index
    • ALL
      • 全表掃描
  • possible_keys:可能用到的索引
  • key:實際上使用的索引
  • key_len:實際使用到的索引長度
    • 對於使用固定長度型別的索引列來說,它實際佔用的儲存空間的最大長度就是該固定值,對於指定字符集的變長型別的索引列來說
    • 如果該索引列可以儲存 NULL 值,則 key_len 比不可以儲存 NULL 值時多1個位元組
    • 對於變長欄位來說,都會有2個位元組的空間來儲存該變長列的實際長度
  • ref:當使用索引列等值查詢時,與索引列進行等值匹配的物件資訊
    • 在訪問方法是 const 、eq_ref、ref、ref_or_null、unique_subquery、index_subquery其中之一時,ref列展示的就是與索引列作等值匹配的東西,可能是一個常量或者一個函式等
  • rows:預估的需要讀取的記錄條數
    • 如果查詢優化器決定使用全表掃描的方式對某個表執行查詢時,執行計劃的rows列就代表預計需要掃描的行數
    • 如果使用索引來執行查詢時,執行計劃的rows列就代表預計掃描的rows索引記錄行數
  • filtered:某個表經過搜尋條件過濾後剩餘記錄條數的百分比
    • 如果使用的是全表掃描的方式執行的單表查詢,那麼計算驅動表扇出時需要估計出滿足搜尋條件的記錄到底有多少條

    • 如果使用的是索引執行的單表掃描,那麼計算驅動表扇出的時候需要估計出滿足除使用到對應索引的搜尋條件外的其他搜尋條件的記錄有多少條


  • Extra:一些額外的資訊
    • No tables used:當查詢語句的沒有FROM語句時將會提示該額外資訊
    • Impossible WHERE:查詢語句的 WHERE 語句永遠為 FALSE 時將會提示該額外資訊
    • No matching min/max row:查詢列表處有MIN或者MAX聚集函式,但是並沒有符合WHERE語句中的搜尋條件的記錄時,將會提示該額外資訊
    • Using index:查詢列表以及搜尋條件中只包含屬於某個索引的列,也就是在可以使用索引覆蓋的情況下,在 Extra 列將會提示該額外資訊
    • Using index condition:有些搜尋條件中雖然出現了索引列,但卻不能使用到索引(索引條件下推:減去好多回表操作的成本(Extra也一樣會顯示Using index condition))
    • Using where
      • 當我們使用全表掃描來執行對某個表的查詢,並且該語句的WHERE語句中有針對該表的搜尋條件時,在 Extra 列中會提示上述額外資訊
      • 當使用索引訪問來執行對某個表的查詢,並且該語句的WHERE語句中有除了該索引包含的列之外的其他搜尋條件時,在 Extra 列中也會提示上述額外資訊
    • Using join buffer (Block Nested Loop)
      • 在連線查詢執行過程中,當被驅動表不能有效的利用索引加快訪問速度,MySQL一般會為其分配一塊名叫 join buffer 的記憶體塊來加快查詢速度,也就是我們所講的基於塊的巢狀迴圈演算法
    • Not exists:當我們使用左/右(外)連線時,如果WHERE語句中包含要求被驅動表的某個列等於NULL值的搜尋條件,並且那個列又是不允許儲存 NULL 值的,那麼在該表的執行計劃的 Extra 列就會提示 Not exists 額外資訊
    • Using intersect(...):準備使用Intersect索引合併的方式執行查詢,括號中的...表示需要進行索引合併的索引名稱
    • Using union(...):準備使用Union索引合併的方式執行查詢
    • Using sort_union(...):說明準備使用Sort-Union索引合併的方式執行查詢
    • Zero limit:LIMIT語句的引數為 0 時,表示壓根兒不打算從表中讀出任何記錄,將會提示該額外資訊
    • Using filesort:有些排序操作無法使用到索引,只能在記憶體中(記錄較少的時候)或者磁碟中(記錄較多的時候)進行排序,就會在執行計劃的 Extra 列中顯示 Using filesort提示;(需要使用filesort的記錄很多時,過程是很耗費效能的)
    • Using temporary:在許多查詢的執行過程中,MySQL可能會藉助臨時表來完成一些功能,比如去重、排序之類的,比如我們在執行許多包含DISTINCT、GROUP BY、UNION等語句的查詢過程中,如果不能有效利用索引來完成查詢,MySQL很有可能尋求通過建立內部的臨時表來執行查詢。如果查詢中使用到了內部的臨時表,在執行計劃的 Extra 列將會顯示 Using temporary 提示
    • Start temporary, End temporary:查詢優化器會優先嚐試將 IN 子查詢轉換成 semijoin ,而 semi-join 會有好多種執行策略,當執行策略為DuplicateWeedout時,也就是通過建立臨時表來實現為外層查詢中的記錄進行去重操作時,驅動表查詢執行計劃的 Extra 列將顯示 Start temporary 提示,被驅動表查詢執行計劃的 Extra列將顯示 End temporary 提示
    • LooseScan:在將In子查詢轉為semi-join時,如果採用的是LooseScan執行策略,則在驅動表執行計劃的Extra列就是顯示LooseScan提示
    • FirstMatch(tbl_name):在將In子查詢轉為semi-join時,如果採用的是FirstMatch執行策略,則在被驅動表執行計劃的Extra列就是顯示FirstMatch(tbl_name) 提示

GROUP BY子句的查詢中預設新增上ORDER BY子句,不想為包含 GROUP BY子句的查詢進行排序,需要我們顯式的寫上ORDER BY NULL 在 EXPLAIN 單詞和真正的查詢語句中間加上 FORMAT=JSON,可以格式化為Json