MySQL執行計劃分析
列名 | 含義 |
---|---|
id | id列,表示查詢中執行select子句或操作表的順序。 |
select_type | 查詢類型,主要是用於區分普通查詢、聯合查詢、子查詢等複雜的查詢。 |
table | 表明對應行正在訪問的是哪個表。 |
partitions | 查詢涉及到的分區。 |
type | 訪問類型,決定如何查找表中的行。 |
possible_keys | 查詢可以使用哪些索引。 |
key | 實際使用的索引,如果為NULL,則沒有使用索引。 |
key_len | 索引中使用的字節數,查詢中使用的索引的長度(最大可能長度),並非實際使用長度,理論上長度越短越好。 |
ref | 顯示索引的那一列被使用。 |
rows | 估算出找到所需行而要讀取的行數。 |
filtered | 返回結果的行數佔讀取行數的百分比,值越大越好。 |
Extra | 額外信息 |
1. id列
id列是一個編號,用於標識SELECT查詢的序列號,表示執行SQL查詢過程中SELECT子句或操作表的順序。
如果在SQL中沒有子查詢或關聯查詢,那麼id列都將顯示一個1。否則,內層的SELECT語句一般會順序編號。
id列分為三種情況:
1)id相同 如下普通查詢,沒有子查詢。
2)id不同 如果存在子查詢,id的序號會遞增,id值越大優先級越高,越先被執行。
3)id相同又不同 1)、2)兩種情況同時存在。 id如果相同,認為是一組,從從上往下執行。在所有組中,id值越大,優先級越高,越先執行。
2.select_type列
select_type列表示對應行的查詢類型,是簡單查詢還是複雜查詢,主要用於區分普通查詢、聯合查詢、子查詢等複雜的查詢。
select_type列有如下值:
select_type值 | 說明 |
---|---|
SIMPLE | 簡單查詢,意味著不包括子查詢或UNION。 |
PRIMARY | 查詢中包含任何復雜的子部分,最外層查詢則被標記為PRIMARY |
SUBQUERY | 在select 或where列表中包含了子查詢 |
DERIVED | 表示包含在from子句的子查詢中的select,MySQL會遞歸執行並將結果放到一個臨時表中,稱其為“派生表”,因為該臨時表是從子查詢中派生而來的。 |
UNION | 第二個select出現在UNION之後,則被標記為UNION。 |
UNION RESULT | 從UNION表獲取結果的select。 |
3.table列
table列表示對應行正在執行的哪張表,指代對應表名,或者該表的別名(如果SQL中定義了別名)。
4.partitions列
查詢涉及到的分區。
5.type列
type列指代訪問類型,是MySQL決定如何查找表中的行,是SQL查詢優化中一個很重要的指標,擁有很多值,依次從最差到最優:
ALL < index < range < index_subquery < unique_subquery < index_merge < ref_or_null < fulltext < ref < eq_ref < const < system
1)ALL
眾所周知的全表掃描,表示通過掃描整張表來找到匹配的行,很顯然這樣的方式查詢速度很慢。 這種情況,性能最差,在寫SQL時盡量避免此種情況的出現。
在平時寫SQL時,避免使用select *,就不難理解了。換言之,是為了避免全表掃描,因為全面掃描是性能最差的。
2)index
全索引掃描,和全表掃描ALL類似,掃描表時按索引次序進行,而不是按行掃描,即:只遍歷索引樹。 index與ALL雖然都是讀全表,但index是從索引中讀取,而ALL是從硬盤讀取。顯然,index性能上優於ALL,合理的添加索引將有助於性能的提升。
3)range
只檢索給定範圍的行,使用一個索引來選擇行。 key列顯示使用了那個索引。一般就是在where語句中出現了bettween、<、>、in等的查詢。這種索引列上的範圍掃描比全索引掃描index要好。
舉例如下: explain select * from film where film_id between 1 and 10;
4)ref
非唯一性索引掃描,返回匹配某個單獨值的所有行。本質是也是一種索引訪問,它返回所有匹配某個單獨值的行,然而它可能會找到多個符合條件的行,所以它屬於查找和掃描的混合體。 此類型只有當使用非唯一索引或者唯一索引的非唯一性前綴時,才會發生。
5)eq_ref
唯一索引掃描。常見於主鍵或唯一索引掃描。
6)const
通過索引一次就能找到,const用於比較primary key 或者unique索引。因為只需匹配一行數據,所有很快。如果將主鍵置於where列表中,mysql就能將該查詢轉換為一個const。 舉例如下: show index from film; explain select * from film where film_id = 1;
7)system
表只有一行記錄,這是const類型的特例,比較少見,如:系統表。
6. possible_keys列
顯示在查詢中使用了哪些索引。
7. key列
實際使用的索引,如果為NULL,則沒有使用索引。查詢中如果使用了覆蓋索引,則該索引僅出現在key列中。 possible_keys列表明哪一個索引有助於更高效的查詢,而key列表明實際優化採用了哪一個索引可以更加高效。 舉例如下: show index from film_actor; explain select actor_id,film_id from film_actor;
8. key_len列
表示索引中使用的字節數,查詢中使用的索的長度(最大可能長度),並非實際使用長度,理論上長度越短越好。 key_len是根據表定義計算而得的,不是通過表內檢索出的。
9. ref列
表示在key列記錄的索引中查找值,所用的列或常量const。
10. rows列
估算出找到所需行而要讀取的行數。 這個數字是內嵌循環關聯計劃裡的循環數,它並不是最終從表中讀取出來的行數,而是MySQL為了找到符合查詢的那些行而必須讀取行的平均數,只能作為一個相對數來進行衡量。
11. filtered列
返回結果的行數佔讀取行數的百分比,值越大越好。
12. Extra列
額外信息,但又十分重要。
常見的值如下:
1)Using index 表示SQL中使用了覆蓋索引。
2)Using where 許多where條件裡是涉及索引中的列,當它讀取索引時,就能被存儲引擎檢驗,因此不是所有帶·where子句的查詢都會顯示“Using where”。
3)Using temporary 對查詢結果排序時,使用了一個臨時表,常見於order by 和group by。
4)Using filesort 對數據使用了一個外部的索引排序,而不是按照表內的索引進行排序讀取。也就是說MySQL無法利用索引完成的排序操作成為“文件排序”。