MySQL執(zhí)行計劃Explain詳解
什么是執(zhí)行計劃
使用 EXPLAIN 關鍵字可以模擬優(yōu)化器執(zhí)行 SQL 查詢語句,從而知道 MySQL 是如何處理你的 SQL 語句的。分析你的查詢語句或是表結構的性能瓶頸
執(zhí)行計劃的作用
- 表的讀取順序
- 數(shù)據(jù)讀取操作的操作類型
- 哪些索引可以使用
- 哪些索引被實際使用
- 表之間的引用
- 每張表有多少行被優(yōu)化器查詢
執(zhí)行計劃的語法
執(zhí)行計劃的語法其實非常簡單:在SQL 查詢的前面加上 EXPLAIN 關鍵字就行。
EXPLAIN select * from table1
重點的就是 EXPLAIN 后面你要分析的 SQL 語句
執(zhí)行計劃詳解
通過 EXPLAIN 關鍵分析的結果由以下列組成,接下來挨個分析每一個列
一、ID 列
ID 列:描述 select 查詢的序列號,包含一組數(shù)字,表示查詢中執(zhí)行 select 子句或操作表的順序
根據(jù) ID 的數(shù)值結果可以分成以下三種情況
- id 相同:執(zhí)行順序由上至下
- id 不同:如果是子查詢,id 的序號會遞增,id 值越大優(yōu)先級越高,越先被執(zhí)行
- id 相同又不同:同時存在
分別舉例來看
Id 相同
如上圖所示,ID 列的值全為 1,代表執(zhí)行的允許從 t1 開始加載,依次為 t3 與 t2
EXPLAIN
select t2.* from t1,t2,t3 where t1.id = t2.id and t1.id = t3.id
and t1.other_column = '';
Id 不同
如果是子查詢,id 的序號會遞增,id 值越大優(yōu)先級越高,越先被執(zhí)行
EXPLAIN
select t2.* from t2 where id = (
select id from t1 where id = (select t3.id from t3 where t3.other_column='')
);
Id 相同又不同
id 如果相同,可以認為是一組,從上往下順序執(zhí)行;
在所有組中,id 值越大,優(yōu)先級越高,越先執(zhí)行
EXPLAIN
select t2.* from (
select t3.id
from t3 where t3.other_column = ''
) s1 ,t2 where s1.id = t2.id
二、select_type 列
Select_type:查詢的類型,
要是用于區(qū)別:普通查詢、聯(lián)合查詢、子查詢等的復雜查詢
類型如下
三、table 列
顯示這一行的數(shù)據(jù)是關于哪張表的
四、Type 列
type 顯示的是訪問類型,是較為重要的一個指標,結果值從最好到最壞依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery >
index_subquery > range > index > ALL
需要記憶的:system>const>eq_ref>ref>range>index>ALL
一般來說,得保證查詢至少達到 range 級別,最好能達到 ref。
System 與 const
System:表只有一行記錄(等于系統(tǒng)表),這是 const 類型的特例,平時不會出現(xiàn),這個也可以忽略不計
Const:表示通過索引一次就找到了。const 用于比較 primary key 或者 unique 索引。因為只匹配一行數(shù)據(jù),所以很快如將主鍵置于 where 列表中,MySQL 就能將該查詢轉(zhuǎn)換為一個常量
eq_ref
唯一性索引掃描,對于每個索引鍵,表中只有一條記錄與之匹配。常見于主鍵或唯一索引掃描
Ref
非唯一性索引掃描,返回匹配某個單獨值的所有行。
本質(zhì)上也是一種索引訪問,它返回所有匹配某個單獨值的行,然而,它可能會找到多個符合條件的行,所以他應該屬于查找和掃描的混合體
Range
只檢索給定范圍的行,使用一個索引來選擇行。key 列顯示使用了哪個索引一般就是在你的 where 語句中出現(xiàn)了 between、<、>、in 等的查詢這種范圍掃描索引掃描比全表掃描要好,因為它只需要開始于索引的某一點,而結束于另一點,不用掃描全部索引。
Index
當查詢的結果全為索引列的時候,雖然也是全部掃描,但是只查詢的索引庫,而沒有去查詢
數(shù)據(jù)
All
Full Table Scan,將遍歷全表以找到匹配的行
五、possible_keys 與 Key列
possible_keys:可能使用的 key
Key:實際使用的索引。如果為 NULL,則沒有使用索引
查詢中若使用了覆蓋索引,則該索引和查詢的 select 字段重疊
EXPLAIN select col1,col2 from t1
其中 key 和 possible_keys 都可以出現(xiàn) null 的情況(結婚邀請朋友的例子)
六、key_len列
desc
select * from ta where col1 ='ab';
desc
select * from ta where col1 ='ab' and col2 = 'ac'
Key_len 表示索引中使用的字節(jié)數(shù),可通過該列計算查詢中使用的索引的長度。在不損失精
確性的情況下,長度越短越好
key_len 顯示的值為索引字段的最大可能長度,并非實際使用長度,即 key_len 是根據(jù)表定義計算而得,不是通過表內(nèi)檢索出的
- key_len 表示索引使用的字節(jié)數(shù),
- 根據(jù)這個值,就可以判斷索引使用情況,特別是在組合索引的時候,判斷所有的索引字段是否都被查詢用到。
- char 和 varchar 跟字符編碼也有密切的聯(lián)系,
- latin1 占用 1 個字節(jié),gbk 占用 2 個字節(jié),utf8 占用 3 個字節(jié)。(不同字符編碼占用的
- 存儲空間不同)
七、Ref列
顯示索引的哪一列被使用了,如果可能的話,是一個常數(shù)。哪些列或常量被用于查找索引列上的值
EXPLAIN
select * from s1 ,s2 where s1.id = s2.id and s1.name = 'enjoy'
由 key_len 可知 t1 表的 idx_col1_col2 被充分使用,col1 匹配 t2 表的 col1,col2 匹配了一個常量,即 'ac'其中 【shared.t2.col1】 為 【數(shù)據(jù)庫.表.列】
八、Rows
根據(jù)表統(tǒng)計信息及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數(shù)
九、Extra
包含不適合在其他列中顯示但十分重要的額外信息。