在平時工做中,常用explain去看sql查詢的查詢計劃,可是有時細節,本身仍是不清楚,所以特此去閱讀官方的文檔,這裏作個記錄以方便本身去理解。mysql
1.explain輸出列sql
+----+---------------+-------+-------+-------------------+---------+-----------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+---------------+-------+-------+--------------------+---------+----------+-------+------+-------+數據庫
列名 | 簡單描述 | 詳細 |
id | 查詢執行的標識 | sql順序大的先執行 |
select_type | 查詢類型 | 查詢類型包括:simple,primary,union,dependent union,union result,subquery,dependence subquery,derived,MATERIALIZED,UNCACHEABLE SUBQUERY,UNCACHEABLE UNION |
table | 查詢用到的表 | 這個表多是臨時表,相似於derived1,說明查詢依賴於第一步查詢的結果 |
type | 鏈接類型 | 從這個列課直觀的知道使用那種鏈接,查詢性能大體是這樣的const>eq_reg>ref>range>index>ALL mysql優化 出all以外,其餘均可以索引,其中index_merge可使用多個索引,其餘只能使用一個性能 |
prossibel_keys | 查詢可能使用到的索引 | 查詢可能使用到的索引 |
key | 查詢實際使用的索引 | 查詢實際使用的索引 |
key_len | 處理查詢使用的索引長度,key_len的計算,列爲NULL佔用1個字節標記,列的長度佔用2個字節,utf-8一個字符佔用3個字節,根據不一樣編碼一個列的key_len字節數就可計算出來,key_len越長查詢效率越差,所以須要注意數據庫字段類型的選取 | |
ref | 指明與索引做比較的列或常量 | |
rows | 完成當前查詢必須掃描的行,在innodb下是估值 | |
Extra | 其餘信息 |
2.查詢類型select_type的常見類型說明優化
類型名稱 | 描述 |
simple | 簡單select,不使用子查詢和union,例如:編碼 select * from t_userspa |
primary | 最外層的select,例如:指針 select * from (select * from t2 where id=5) a排序 |
union | union中的第二個或者後面的語句,例如: select * from xx where id=5 union all select * from x3 |
dependent union | union中的第二個或者後面的語句,依賴於最外層的查詢
|
union result | union後的結果,例如 select * from xx where id=5 union all select * from x3 |
subquery | 子查詢中的第一個select |
dependent subquery | 子查詢中的第一個select,依賴於最外層的查詢
|
derived | 派生表的select,一般from語句中的子查詢。例如: select * from (select * from xx where id=45) a ; |
3聯接類型type說明
類型名稱 | 說明 |
system | 表只有一行數據,是一種特殊的const,例如: select * from (select * from xx where id=45) a ; |
const | 表中至多隻有一條數據匹配條件,例如: select * from user where id = 1,id是主鍵只有一條數據知足 |
eq_ref | 對於每一個來自於前面的表的行組合,從該表中讀取一行。這多是最好的聯接類型,除了const類型。它用在一個索引的全部部分被聯接使用而且索引是UNIQUE或PRIMARY KEY(ps:前驅表只返回一條數據,且這行數據是第二個表的主鍵或者惟一索引) |
ref | 對於每一個來自於前面的表的行組合,全部有匹配索引值的行將從這張表中讀取。若是聯接只使用鍵的最左邊的前綴,或若是鍵不是UNIQUE或PRIMARY KEY(換句話說,若是聯接不能基於關鍵字選擇單個行的話),則使用ref。若是使用的鍵僅僅匹配少許行,該聯接類型是不錯的。 ref能夠用於使用=或<=>操做符的帶索引的列 |
fulltext | 使用fulltext索引 |
ref_or_null | 該聯接類型如同ref,可是添加了MySQL能夠專門搜索包含NULL值的行。在解決子查詢中常用該聯接類型的優化 |
index_merge | 使用索引合併優化,在這種狀況下,key列包含了使用的索引的清單,key_len包含了使用的索引的最長的關鍵元素 |
unique_subquery | 用於替代in子查詢的ref,通常是where in字句,字句返回不重複惟一值 |
index_subquery | 和unique_subquery類似,只是where in字句使用的字句返回的值不是惟一值可能重複(ps:非惟一索引) |
range | 只檢索給定範圍的行(ps:索引範圍掃描),使用一個索引來選擇行。key列顯示使用了哪一個索引。key_len包含所使用索引的最長關鍵元素。在該類型中ref列爲NULL。 當使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操做符,用常量比較關鍵字列時,可使用range |
index | 該聯接類型與ALL相同,除了只有索引樹被掃描。這一般比ALL快,由於索引文件一般比數據文件小。 當查詢只使用做爲單索引一部分的列時,MySQL可使用該聯接類型。 |
all | 使用全表掃描 |
4.Extra
extral顯示mysql是如何處理查詢的。
類型名稱 | 描述 |
distinct | mysql找到匹配的行就不在搜索了 |
Impossible where | where查詢語句錯誤,不能查詢到任何結果 |
Impossible having | having字句錯誤,不能查詢到任何結果 |
not exists | mysql優化了left join查詢,一旦找到匹配left join標準的行就不在 搜索,例如:select * from t1 left join t2 on t1.id = t2.id where t2.id is null 假設t2的id是不能爲null的,這時就會被優化 |
using filesort | 若是出現了該項,則說明查詢須要優化,MYSQL須要進行額外的步驟來發現如何對返回的行排序。它根據鏈接類型以及存儲排序鍵值和匹配條件的所有行的行指針來排序所有行(ps:從磁盤或內存進行排序,沒法使用索引排序) |
using index | 列數據僅僅使用了索引樹種的信息,並無作額外的操做去讀取實際的行,這發生在對錶的所有的請求列都是同一個索引的部分的時候 |
using index condition | where條件包含索引或者非索引的列,優化器首先使用索引的列去表中檢索信息而後在根據其餘條件檢索出記錄 |
using where | where語句沒有使用索引,或者索引列可爲空 |
using temporary | 爲了處理查詢,mysql須要額外的建立一個零時表來容納結果,典型的例子就group by和order by。 對於group by和order by的查詢爲了不出現using temporary,肯定驅動表(ps:優化器通常將記錄少的作驅動表),,聚合和排序使用的驅動表的字段 |