面試前必須知道的MySQL命令【explain】

Java3y發表於2018-12-06

前言

只有光頭才能變強

刷面試題的時候,不知道你們有沒有見過MySQL這兩個命令:explainprofile(反正我就見過了)..

之前雖然知道這兩個命令大概什麼意思,但一直沒有去做筆記。今天發現自己的TODO LIST有這麼兩個命令,於是打算來學習一番,記錄一下~

使用的MySQL的版本為5.6.38

MySQL版本

一、explain命令

1.1體驗explain命令

首先我們來體驗一下explain命令是怎麼使用的,以及輸出的結果是什麼:


explain select * from table_user ;

複製程式碼

輸出結果:

體驗explain命令

發現很使用起來很簡單,只要explain後邊跟著SQL語句就完事了(MySQL5.6之前的版本,只允許解釋SELECT語句,從 MySQL5.6開始,非SELECT語句也可以被解釋了)。

1.2為什麼需要explain命令

我們很多時候編寫完一條SQL語句,往往想知道這條SQL語句執行是否高效。或者說,我們建立好的索引在這條SQL語句中是否使用到了,就可以使用explain命令來分析一下!

  • 簡單來說:通過explain命令我們可以學習到該條SQL是如何執行的,隨後解析explain的結果可以幫助我們使用更好的索引,最終來優化它!

通過explain命令我們可以知道以下資訊:表的讀取順序,資料讀取操作的型別,哪些索引可以使用,哪些索引實際使用了,表之間的引用,每張表有多少行被優化器查詢等資訊。

// 好了,我們下面看一下explain出來的結果是怎麼看的。

1.3讀懂explain命令結果

explain命令輸出的結果有10列:id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra

1.3.1id

包含一組數字,表示查詢中執行SELECT子句或操作表的順序

在id列上也會有幾種情況:

  • 如果id相同執行順序由上至下。
  • 如果id不相同,id的序號會遞增,id值越大優先順序越高,越先被執行。
    • (一般有子查詢的SQL語句id就會不同)

explain一下擁有子查詢的SQL

1.3.2select_type

表示select查詢的型別

select_type屬性下有好幾種型別:

  • SIMPLLE:簡單查詢,該查詢不包含 UNION 或子查詢
  • PRIMARY:如果查詢包含UNION 或子查詢,則最外層的查詢被標識為PRIMARY
  • UNION:表示此查詢是 UNION 中的第二個或者隨後的查詢
  • DEPENDENT:UNION 滿足 UNION 中的第二個或者隨後的查詢,其次取決於外面的查詢
  • UNION RESULT:UNION 的結果
  • SUBQUERY:子查詢中的第一個select語句(該子查詢不在from子句中)
  • DEPENDENT SUBQUERY:子查詢中的 第一個 select,同時取決於外面的查詢
  • DERIVED:包含在from子句中子查詢(也稱為派生表)
  • UNCACHEABLE SUBQUERY:滿足是子查詢中的第一個 select 語句,同時意味著 select 中的某些特性阻止結果被快取於一個 Item_cache 中
  • UNCACHEABLE UNION:滿足此查詢是 UNION 中的第二個或者隨後的查詢,同時意味著 select 中的某些特性阻止結果被快取於一個 Item_cache 中

型別有點多啊,我加粗的是最常見的,起碼要看得懂加粗的部分。

1.3.3table

該列顯示了對應行正在訪問哪個表(有別名就顯示別名)。

當from子句中有子查詢時,table列是 <derivenN>格式,表示當前查詢依賴 id=N的查詢,於是先執行 id=N 的查詢

1.3.4type

該列稱為關聯型別或者訪問型別,它指明瞭MySQL決定如何查詢表中符合條件的行,同時是我們判斷查詢是否高效的重要依據

以下為常見的取值

  • ALL:全表掃描,這個型別是效能最差的查詢之一。通常來說,我們的查詢不應該出現 ALL 型別,因為這樣的查詢,在資料量最大的情況下,對資料庫的效能是巨大的災難。
  • index:全索引掃描,和 ALL 型別類似,只不過 ALL 型別是全表掃描,而 index 型別是掃描全部的索引,主要優點是避免了排序,但是開銷仍然非常大。如果在 Extra 列看到 Using index,說明正在使用覆蓋索引,只掃描索引的資料,它比按索引次序全表掃描的開銷要少很多。
  • range:範圍掃描,就是一個有限制的索引掃描,它開始於索引裡的某一點,返回匹配這個值域的行。這個型別通常出現在 =、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN、IN() 的操作中,key 列顯示使用了哪個索引,當 type 為該值時,則輸出的 ref 列為 NULL,並且 key_len 列是此次查詢中使用到的索引最長的那個。
  • ref:一種索引訪問,也稱索引查詢,它返回所有匹配某個單個值的行。此型別通常出現在多表的 join 查詢, 針對於非唯一或非主鍵索引, 或者是使用了最左字首規則索引的查詢。
  • eq_ref:使用這種索引查詢,最多隻返回一條符合條件的記錄。在使用唯一性索引或主鍵查詢時會出現該值,非常高效。
  • const、system:該表至多有一個匹配行,在查詢開始時讀取,或者該表是系統表,只有一行匹配。其中 const 用於在和 primary key 或 unique 索引中有固定值比較的情形。
  • NULL:在執行階段不需要訪問表。

1.3.5possible_keys

這一列顯示查詢可能使用哪些索引來查詢

1.3.6key

這一列顯示MySQL實際決定使用的索引。如果沒有選擇索引,鍵是NULL。

1.3.7key_len

這一列顯示了在索引裡使用的位元組數,當key列的值為 NULL 時,則該列也是 NULL

1.3.8ref

這一列顯示了哪些欄位或者常量被用來和key配合從表中查詢記錄出來。

1.3.9rows

這一列顯示了估計要找到所需的行而要讀取的行數,這個值是個估計值,原則上值越小越好。

1.3.10extra

其他的資訊

常見的取值如下:

  • Using index:使用覆蓋索引,表示查詢索引就可查到所需資料,不用掃描表資料檔案,往往說明效能不錯。
  • Using Where:在儲存引擎檢索行後再進行過濾,使用了where從句來限制哪些行將與下一張表匹配或者是返回給使用者。
  • Using temporary:在查詢結果排序時會使用一個臨時表,一般出現於排序、分組和多表 join 的情況,查詢效率不高,建議優化。
  • Using filesort:對結果使用一個外部索引排序,而不是按索引次序從表裡讀取行,一般有出現該值,都建議優化去掉,因為這樣的查詢 CPU 資源消耗大。

最後

原本以為Explain命令是比較難學的,但查詢資料看下來,之前只是不知道具體的列和列中下的屬性是什麼意思而已。常見出現的其實也就那麼幾個,感覺對著每個屬性多看一會,還是可以能看懂的。

當然了,在《高效能MySQL》中也有複雜的SQL語句來分析(但我認為我們一般不會寫到那麼複雜)..

這篇文章也借鑑了很多其他優秀的部落格,如果大家有興趣的話可以去閱讀一下:

如果你覺得我寫得還不錯,瞭解一下:

  • 堅持原創的技術公眾號:Java3y。
  • 文章的目錄導航(精美腦圖+海量視訊資源):

帥的人都關注了

相關文章