1. 程式人生 > >mysql 學習與提高5:explain命令詳解

mysql 學習與提高5:explain命令詳解

目錄

Explain 簡介

Explain 使用

Explain 欄位

1. id欄位

2.select_type

3.table

4.type

5.possible_keys

6.key

7.key_len

8.ref

9.rows

10.extra

注意事項


Explain 簡介

Explain 提供了 MySQL 如何執行 SQL 語句的資訊,通過這些資訊,可以對 SQL 語句做相應的優化,提高執行效率。

Explain 使用

呼叫 Explain,只需要在 SQL 語句前新增 explain 關鍵字即可。

一般情況下,新增 explain 關鍵字後,認為 MySQL 不會執行查詢,但是如果在 from 子句中包含子查詢,那麼 MySQL 實際上會執行子查詢,將其子查詢的結果放在一個臨時表中,然後完成外層查詢優化。

MySQL 5.6 之前的版本,只允許解釋 select 語句,從 MySQL 5.6 開始,非 select 語句也可以被解釋了。

Explain 欄位

呼叫 Explain 後,MySQL 會返回一行或者多行記錄,通過這些記錄就可以知道 SQL 語句的執行情況了。

例如:執行語句

EXPLAIN select * from student where name = 'Bill'

 

每行記錄都包含了以下幾個欄位

  • id:執行編號,標識 select 所屬的行
  • select_type:select 查詢的型別
  • table:查詢的是哪個表
  • partitions:匹配的分割槽
  • type:關聯型別,索引型別
  • possible_keys:該查詢可以選用的索引
  • key:該查詢選用的索引
  • key_len:索引中使用的位元組數
  • ref:顯示上述表的連線匹配條件,即哪些列或常量被用於查詢索引列上的值
  • rows:估計為了找到所需行而要讀取的行數
  • filtered:按表條件過濾的行的百分比
  • Extra:額外的資訊

接下來我們逐個進行講解

1. id欄位

  •  id值相同,從上往下 順序執行。  
  • id值不同:id值越大越優先查詢 (本質:在巢狀子查詢時,先查內層 再查外層)
  • id值有相同,又有不同: id值越大越優先;id值相同,從上往下 順序執行

注意:我們發現,表的執行順序會因為表中資料的個數改變而改變,這是什麼原因呢?

假設我們有 a(4)  b(3)  c(3)三種表,括號內的是其資料個數。

當執行語句 select * from a,b,c時

若執行順序為  b--- c--- a  時,根據笛卡爾積  3 * 2 = 6 * 4 = 24 ,中間結果 6 需要佔用儲存空間進行儲存

若執行順序為  a--- b--- c  時,根據笛卡爾積  4 * 3 =12 * 2 = 24 ,中間結果12需要佔用儲存空間進行儲存

這兩種最後的執行結果是一樣的,但是前一種順序比後一種順序的中間結果更小,意味著需要更小的儲存空間,所以mysql會自動對錶的執行順序進行調整,資料少的表先查詢。

2.select_type

select_type表示了查詢的型別,它的常用取值有

  • SIMPLE, 表示此查詢不包含 UNION 查詢或子查詢
  • PRIMARY, 表示此查詢是最外層的查詢
  • UNION, 表示此查詢是 UNION 的第二或隨後的查詢
  • DEPENDENT UNION, UNION 中的第二個或後面的查詢語句, 取決於外面的查詢
  • UNION RESULT, UNION 的結果
  • SUBQUERY, 子查詢中的第一個 SELECT
  • DEPENDENT SUBQUERY: 子查詢中的第一個 SELECT, 取決於外面的查詢. 即子查詢依賴於外層查詢的結果.

3.table

表示查詢涉及的表或衍生表

//執行如下多表查詢
EXPLAIN SELECT * FROM teacher t,course c where t.t_cid = c.c_id;

 

4.type

該列稱為關聯型別或者訪問型別,它指明瞭 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:在執行階段不需要訪問表。

該列取不同值的執行效率依次是

ALL < index < range < ref < eq_ref < const < system < NULL

其中:system,const只是理想情況;實際能達到 ref>range

index 和 all的區別

index:查詢全部索引中資料
explain select tid from teacher ; --tid 是索引, 只需要掃描索引表,不需要所有表中的所有資料
all:查詢全部表中的資料
explain select cid from course ;  --cid不是索引,需要全表所有,即需要所有表中的所有資料

5.possible_keys

表示 MySQL 在查詢時, 能夠使用到的索引. 注意, 即使有些索引在 possible_keys 中出現, 但是並不表示此索引會真正地被 MySQL 使用到. MySQL 在查詢時具體使用了哪些索引, 由 key 欄位決定.

6.key

此欄位是 MySQL 在當前查詢時所真正使用到的索引.

7.key_len

索引的長度 ;一般用於判斷複合索引是否被完全使用  (a,b,c)。

eg:先增加一個表,並把name設為索引

create table test_kl
(
	name char(20) not null default ''
);
alter table test_kl add index index_name(name) ;

 執行explain語句

explain select * from test_kl where name =''

這個60是怎麼算的呢? 其實是60 = 20 * 3這樣得來的, 20表示每個name佔20個字元,3表示在utf8中1個字元站3個位元組,所以  便得到了我們的60

 我們繼續在原來的基礎上再增加一個不為空的name1欄位,並設定為索引


alter table test_kl add column name1 char(20) ;  --name1可以為null

alter table test_kl add index index_name1(name1) ;
explain select * from test_kl where name1 ='' ; 

此時ken_len為61,是因為如果索引欄位可以為Null,則會使用1個位元組用於標識。 

key_len的計算規則如下:

​​​​​

  • 字串

    • char(n): n 位元組長度

    • varchar(n): 如果是 utf8 編碼, 則是 3 n + 2位元組; 如果是 utf8mb4 編碼, 則是 4 n + 2 位元組.

  • 數值型別:

    • TINYINT: 1位元組

    • SMALLINT: 2位元組

    • MEDIUMINT: 3位元組

    • INT: 4位元組

    • BIGINT: 8位元組

  • 時間型別

    • DATE: 3位元組

    • TIMESTAMP: 4位元組

    • DATETIME: 8位元組

  • 欄位屬性: NULL 屬性 佔用一個位元組. 如果一個欄位是 NOT NULL 的, 則沒有此屬性.

8.ref

注意與type中的ref值區分。作用: 指明當前表所 參照的 欄位。
select ....where a.c = b.x ;(其中b.x可以是常量,const)

9.rows

rows 也是一個重要的欄位. MySQL 查詢優化器根據統計資訊, 估算 SQL 要查詢到結果集需要掃描讀取的資料行數.
這個值非常直觀顯示 SQL 的效率好壞, 原則上 rows 越少越好.

10.extra

該列顯示了有關 MySQL 如何解析查詢的其它資訊。

以下為常見的取值

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

注意事項

  • Explain 不會告訴你觸發器、儲存過程或使用者自定義函式對查詢的影響情況; 

 

  • Explain 不會告訴你 MySQL 在查詢執行中所做的特定優化; 

 

  • Explain 只是個近似結果; 

 

  • Explain 不會顯示關於查詢的執行計劃的所有資訊。