執行計划詳解
通過EXPLAIN關鍵分析的結果由以下列組成,接下來挨個分析每一個列
1. ID列
ID列:描述select查詢的序列號,包含一組數字,表示查詢中執行select子句或操作表的順序
根據ID的數值結果可以分成一下三種情況
l id相同:執行順序由上至下
l id不同:如果是子查詢,id的序號會遞增,id值越大優先級越高,越先被執行
2. select_type列
Select_type:查詢的類型,
要是用於區別:普通查詢、聯合查詢、子查詢等的復雜查詢
類型如下
2.1. SIMPLE
EXPLAIN select * from t1
簡單的 select 查詢,查詢中不包含子查詢或者UNION
2.2. PRIMARY與SUBQUERY
PRIMARY:查詢中若包含任何復雜的子部分,最外層查詢則被標記為
SUBQUERY:在SELECT或WHERE列表中包含了子查詢
EXPLAIN
select t1.*,(select t2.id from t2 where t2.id = 1 ) from t1
2.3. DERIVED
在FROM列表中包含的子查詢被標記為DERIVED(衍生)
MySQL會遞歸執行這些子查詢, 把結果放在臨時表里。
select t1.* from t1 ,(select t2.* from t2 where t2.id = 1 ) s2 where t1.id = s2.id
2.4. UNION RESULT 與UNION
UNION:若第二個SELECT出現在UNION之后,則被標記為UNION;
UNION RESULT:從UNION表獲取結果的SELECT
#UNION RESULT ,UNION
EXPLAIN
select * from t1
UNION
select * from t2
3. table列
顯示這一行的數據是關於哪張表的
4.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。
4.1. System與const
System:表只有一行記錄(等於系統表),這是const類型的特列,平時不會出現,這個也可以忽略不計
Const:表示通過索引一次就找到了
const用於比較primary key或者unique索引。因為只匹配一行數據,所以很快
如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量
4.2. eq_ref
唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或唯一索引掃描
EXPLAIN
SELECT * from t1,t2 where t1.id = t2.id
4.3. Ref
非唯一性索引掃描,返回匹配某個單獨值的所有行.
本質上也是一種索引訪問,它返回所有匹配某個單獨值的行,然而,它可能會找到多個符合條件的行,所以他應該屬於查找和掃描的混合體
EXPLAIN
select count(DISTINCT col1) from t1 where col1 = 'ac'
或者
EXPLAIN
select col1 from t1 where col1 = 'ac'
4.4. Range
只檢索給定范圍的行,使用一個索引來選擇行。key 列顯示使用了哪個索引
一般就是在你的where語句中出現了between、<、>、in等的查詢
這種范圍掃描索引掃描比全表掃描要好,因為它只需要開始於索引的某一點,而結束語另一點,不用掃描全部索引。
EXPLAIN select * from t1 where id BETWEEN 30 and 60
EXPLAIN select * from t1 where id in(1,2)
4.5. Index
當查詢的結果全為索引列的時候,雖然也是全部掃描,但是只查詢的索引庫,而沒有去查詢
數據。
EXPLAIN
select c2 from testdemo
4.6. All
Full Table Scan,將遍歷全表以找到匹配的行
5. possible_keys 與Key
possible_keys:可能使用的key
Key:實際使用的索引。如果為NULL,則沒有使用索引
查詢中若使用了覆蓋索引,則該索引和查詢的select字段重疊
EXPLAIN select col1,col2 from t1
其中key和possible_keys都可以出現null的情況
6. key_len
Key_len表示索引中使用的字節數,可通過該列計算查詢中使用的索引的長度。在不損失精確性的情況下,長度越短越好
key_len顯示的值為索引字段的最大可能長度,並非實際使用長度,即key_len是根據表定義計算而得,不是通過表內檢索出的
l key_len表示索引使用的字節數,
l 根據這個值,就可以判斷索引使用情況,特別是在組合索引的時候,判斷所有的索引字段是否都被查詢用到。
l char和varchar跟字符編碼也有密切的聯系,
l latin1占用1個字節,gbk占用2個字節,utf8占用3個字節。(不同字符編碼占用的存儲空間不同)
字符類型-索引字段為char類型+不可為Null時
CREATE TABLE `s1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(10) NOT NULL,
`addr` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
explain select * from s1 where name='enjoy';
name這一列為char(10),字符集為utf-8占用3個字節
Keylen=10*3
字符類型-索引字段為char類型+允許為Null時
CREATE TABLE `s2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(10) DEFAULT NULL,
`addr` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
explain select * from s2 where name='enjoyedu';
name這一列為char(10),字符集為utf-8占用3個字節,外加需要存入一個null值
Keylen=10*3+1(null) 結果為31
索引字段為varchar類型+不可為Null時
CREATE TABLE `s3` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) NOT NULL,
`addr` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
explain select * from s3 where name='enjoyeud';
Keylen=varchar(n)變長字段+不允許Null=n*(utf8=3,gbk=2,latin1=1)+2
索引字段為varchar類型+允許為Null時
CREATE TABLE `s3` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) NOT NULL,
`addr` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
explain select * from s3 where name='enjoyeud';
Keylen=varchar(n)變長字段+允許Null=n*(utf8=3,gbk=2,latin1=1)+1(NULL)+2
6.2. 數值類型
6.3.日期和時間
datetime類型在5.6中字段長度是5個字節
datetime類型在5.5中字段長度是8個字節
復合索引有最左前綴的特性,如果復合索引能全部使用上,則是復合索引字段的索引長度之和,這也可以用來判定復合索引是否部分使用,還是全部使用。
7. Ref
顯示索引的哪一列被使用了,如果可能的話,是一個常數。哪些列或常量被用於查找索引列上的值
8. Rows
根據表統計信息及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數
9. Extra
包含不適合在其他列中顯示但十分重要的額外信息。
9.3. Using index
表示相應的select操作中使用了覆蓋索引(Covering Index),避免訪問了表的數據行,效率不錯!
如果同時出現using where,表明索引被用來執行索引鍵值的查找;
如果沒有同時出現using where,表明索引用來讀取數據而非執行查找動作