1. 程式人生 > 其它 >Explain分析SQL語句

Explain分析SQL語句

技術標籤:原始碼分析資料庫mysql

文章目錄


一、Explain

使用EXPLAIN關鍵字可以模擬優化器執行SQL語句,分析查詢語句或是結構的效能瓶頸 在 select 語句之前增加 explain關鍵字,MySQL 會在查詢上設定一個標記,執行查詢會返 回執行計劃的資訊,而不是執行這條SQL 注意:如果 from中包含子查詢,仍會執行子查詢,將結果放入臨時表中

explain 兩個變種
1)explain extended:會在 explain 的基礎上額外提供一些查詢優化的資訊。緊隨其後通 過 show warnings 命令可以得到優化後的查詢語句,從而看出優化器優化了什麼。額外還有 filtered 列,是一個半分比的值,rows * filtered/100 可以估算出將要和 explain 中前一個表 進行連線的行數(前一個表指 explain 中的id值比當前表id值小的表)。 mysql> explain extended select * from film where id = 1;
在這裡插入圖片描述

mysql> show warnings
;

在這裡插入圖片描述
2)explain partitions:相比 explain 多了個 partitions 欄位,如果查詢是基於分割槽表的 話,會顯示查詢將訪問的分

二、explain中的列

1. id列

id列的編號是 select 的序列號,有幾個 select 就有幾個id,並且id的順序是按 select 出現的 順序增長的。 id列越大執行優先順序越高,id相同則從上往下執行,id為NULL最後執行

2. select_type列

select_type 表示對應行是簡單還是複雜的查詢。
1)simple:簡單查詢。查詢不包含子查詢和union
2)primary:複雜查詢中最外層的 select

3)subquery:包含在 select 中的子查詢(不在 from 子句中)
4)derived:包含在 from 子句中的子查詢。MySQL會將結果存放在一個臨時表中,也稱為 派生表(derived的英文含義)
5)union:在 union 中的第二個和隨後的 select

3. table列

這一列表示 explain 的一行正在訪問哪個表。 當 from 子句中有子查詢時,table列是 格式,表示當前查詢依賴 id=N 的查 詢,於是先執行 id=N 的查詢。 當有 union 時,UNION RESULT 的 table 列的值為<union1,2>,1和2表示參與 union 的 select 行id

4. type列

這一列表示關聯型別或訪問型別,即MySQL決定如何查詢表中的行,查詢資料行記錄的大概 範圍。 依次從最優到最差分別為:system > const > eq_ref > ref > range > index > ALL 一般來說,得保證查詢達到range級別,最好達到ref

const, system:mysql能對查詢的某部分進行優化並將其轉化成一個常量(可以看show warnings 的結果)。用於 primary key 或 unique key 的所有列與常數比較時,所以表最多 有一個匹配行,讀取1次,速度比較快。system是const的特例,表裡只有一條元組匹配時為 system
eg:

mysql> explain extended select * from (select * from film where id = 1) tmp;

在這裡插入圖片描述

mysql> show warnings;

在這裡插入圖片描述

eq_ref: primary key 或 unique key 索引的所有部分被連線使用 ,最多隻會返回一條符合 條件的記錄。這可能是在 const 之外最好的聯接型別了,簡單的 select 查詢不會出現這種 type。

mysql> explain select * from film_actor left join film on film_actor.film_id = film.id;

在這裡插入圖片描述
**ref:**相比 eq_ref,不使用唯一索引,而是使用普通索引或者唯一性索引的部分字首,索引要 和某個值相比較,可能會找到多個符合條件的行。 1. 簡單 select 查詢,name是普通索引(非唯一索引)

mysql> explain select * from film where name = 'film1'

在這裡插入圖片描述
range:範圍掃描通常出現在 in(), between ,> ,<, >= 等操作中。使用一個索引來檢索給定 範圍的行。

 mysql> explain select * from actor where id > 1;

在這裡插入圖片描述
index:掃描全表索引,這通常比ALL快一些。

 mysql> explain select * from film;

在這裡插入圖片描述
**ALL:**即全表掃描,意味著mysql需要從頭到尾去查詢所需要的行。通常情況下這需要增加索 引來進行優化了

mysql> explain select * from actor;

5.possible_keys列

這一列顯示查詢可能使用哪些索引來查詢。 explain 時可能出現 possible_keys 有列,而 key 顯示 NULL 的情況,這種情況是因為表中 資料不多,mysql認為索引對此查詢幫助不大,選擇了全表查詢。 如果該列是NULL,則沒有相關的索引。在這種情況下,可以通過檢查 where 子句看是否可 以創造一個適當的索引來提高查詢效能,然後用 explain 檢視效果。

6. key列

這一列顯示mysql實際採用哪個索引來優化對該表的訪問。 如果沒有使用索引,則該列是 NULL。如果想強制mysql使用或忽視possible_keys列中的索 引,在查詢中使用 force index、ignore index。

7. key_len列

這一列顯示了mysql在索引裡使用的位元組數,通過這個值可以算出具體使用了索引中的哪些 列。舉例來說,film_actor的聯合索引 idx_film_actor_id 由 film_id 和 actor_id 兩個int列組成, 並且每個int是4位元組。通過結果中的key_len=4可推斷出查詢使用了第一個列:film_id列來執 行索引查詢。

mysql> explain select * from film_actor where film_id = 2;

在這裡插入圖片描述

key_len計算規則如下:

字串 char(n):n位元組長度 varchar(n):2位元組儲存字串長度,如果是utf-8,則長度 3n + 2

數值型別tinyint:1位元組 smallint:2位元組 int:4位元組 bigint:8位元組

時間型別date:3位元組 timestamp:4位元組 datetime:8位元組

如果欄位允許為 NULL,需要1位元組記錄是否為 NULL

索引最大長度是768位元組,當字串過長時,mysql會做一個類似左字首索引的處理,將前半 部分的字元提取出來做索引。

8. ref列

這一列顯示了在key列記錄的索引中,表查詢值所用到的列或常量,常見的有:const(常 量),欄位名(例:film.id)

9. rows列

這一列是mysql估計要讀取並檢測的行數,注意這個不是結果集裡的行數。

10. Extra列

這一列展示的是額外資訊。常見的重要值如下:

Using index:使用覆蓋索引

 mysql> explain select film_id from film_actor where film_id = 1;

在這裡插入圖片描述
Using where:使用 where 語句來處理結果,查詢的列未被索引覆蓋

 mysql> explain select * from actor where name = 'a';

在這裡插入圖片描述
Using index condition:查詢的列不完全被索引覆蓋,where條件中是一個前導列的範 圍;

mysql> explain select * from film_actor where film_id > 1;

在這裡插入圖片描述
Using temporary:mysql需要建立一張臨時表來處理查詢。出現這種情況一般是要進行 優化的,首先是想到用索引來優化。

  1. actor.name沒有索引,此時建立了張臨時表來distinct
 mysql> explain select distinct name from actor;

在這裡插入圖片描述

  1. film.name建立了idx_name索引,此時查詢時extra是using index,沒有用臨時表
mysql> explain select distinct name from film;

在這裡插入圖片描述
Using filesort:將用外部排序而不是索引排序,資料較小時從記憶體排序,否則需要在磁碟 完成排序。這種情況下一般也是要考慮使用索引來優化的。

  1. actor.name未建立索引,會瀏覽actor整個表,儲存排序關鍵字name和對應的id,然後排 序name並檢索行記錄
mysql> explain select * from actor order by name;

在這裡插入圖片描述

  1. film.name建立了idx_name索引,此時查詢時extra是using index
mysql> explain select * from film order by name;

在這裡插入圖片描述

Select tables optimized away:使用某些聚合函式(比如 max、min)來訪問存在索引 的某個欄位是

mysql> explain select min(id) from film;

在這裡插入圖片描述