首先我們來看一下什麼是執行計劃:
執行計劃就是解釋select語句如何在資料庫執行的、相關表是怎麼連接、連接的次序、有哪些索引和索引使用情況、每個表的掃描數據量等等。 簡單來說,就是通過數據來分析select語句的執行情況;
怎麼查看執行計劃:查看執行需要用到關鍵字EXPLAIN,將EXPLAIN放在SQL語句的前面( EXPLAIN [EXTENDED] SELECT select_options ),如下圖:
從上圖可以看出,通過執行計劃展示了表格數據,這個表格有id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、filtered、extra等欄位的信息,這些欄位分別表示什麼意思呢?下面具體介紹下:
1、id
執行計劃的id 是select查詢的序列號,標識執行順序。注意有兩種情況,具體如下:
1)、當id相同時,執行順序從上到下執行。
左外連接,先執行左邊後執行右邊(例如:select * from user u left join custom_order co on u.id=co.creater 會先執行user表後執行custom_order),在執行計劃中,user表應該在上面,custom_order在下面,如下圖:
右外連接,先執行右邊後執行左邊(例如: select * from user u right join custom_order co on u.id=co.creater 會先執行custom_order表後執行user表),在執行計劃中,custom_order表應該在上面,user在下面,如下圖:
從上面的執行結果來看,和預計的一樣。
2)、當id不相同時,id越大越先執行。
例如:select * from user where id=(select creater from custom_order where id=1),這個語句中的子查詢會比主查詢會先執行。那在explain select * from user where id=(select creater from custom_order where id=1) 中 custom_order 的id應該是2,user的id應該是1,實際是不是這樣呢,如下圖:
從結果中可以知道,執行結果和預計的一樣;
2、select_type
執行計劃的select_type是select語句的類型,用於區分各種查詢;具體類型有以下幾種:
1)、SIMPLE
簡單的select語句,不使用union或子查詢。如下圖:
2)、PRIMARY
最外層的select語句。如下圖
3)、UNION
union中的第二個或後面的select語句。如下圖
4)、DEPENDENT UNION
union中的第二個或後面的select語句,取決於外面的查詢。如下圖
5)、UNION RESULT
union的結果。如下圖
6)、SUBQUERY
子查詢的第一個select語句。如下圖
7)、DEPENDENT SUBQUERY
子查詢中的第一個select語句,取決於外面的查詢。如下圖
8)、DERIVED
衍生表的select語句(在from列表中包含的子查詢)。如下圖
3、table
語句查詢中所涉及到的表。如下圖:
4、partitions
查詢涉及到的分區別。如下圖:
5、type
SQL語句的連接類型。具體個連接類型如下:(按照從效率高的類型到效率低的類型進行排序)
1)、system
表僅有一行(等於系統表)。這是const連接類型的一種特例。
2)、const
表最多有一個匹配行,它將在查詢開始時被讀取,常用於主鍵或唯一索引的定值查詢。因為匹配行只有一行,所以查詢速度很快。如下圖(id是主鍵):
3)、eq_ref
唯一性索引掃描,對於前表的每一行,表中只有一行與之相匹配或者沒有能匹配。常見於主鍵或唯一索引掃描。是除const類型和system類型外最快的類型。如下圖:
4)、ref
非唯一性索引掃描,對於前表的每一行,表中可存在多個與之相匹配的行。如下圖:
5)、ref_or_null
和ref類型一樣,但是添加了mysql可以專門搜索包含NULL值的行。如下圖:
6)、index_merge
標識使用了索引合併優化方法。如下圖:
7)、unique_subquery
一個索引查找函數,可以完全替換子查詢,效率更高。
8)、index_sugquery
類似於unique_subquery。可以替換IN子查詢,但只適合下列形式的子查詢中的非唯一索引。
9)、range
只檢索給定範圍的行,使用一個索引來選擇行。key列顯示使用了哪個索引。key_len包含所使用索引的最長關鍵元素。在該類型中ref列為NULL。當使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比較關鍵字列時。如下圖:
10)、index
掃描索引樹。如果索引是複合索引,並且複合索引列滿足select所需的所有數據,則僅掃描索引樹,不需要回表。如下圖:
11)、ALL
掃描全表。這是最差的情況,沒有索引,進行完整的表掃描。如下圖:
6、possible_keys
語句中能使用索引有哪些。如下圖:
7、key
該語句執行的時候是使用的哪條索引。如下圖:
8、key_len該語句執行時使用的索引長度(字節數)。如下圖:
9、ref
該表的索引欄位關聯了哪張表的哪個欄位。如下圖:
10、rows
該語句執行時需要讀取行數,數越小越好。如下圖:
11、filtered
該語句返回結果的行數佔讀取行數的百分比,值越大越好。如下圖:
12、extra
十分重要的額外信息。常見的如下:
1)、Distinct
MySQL發現第一個匹配的行後,停止為當前索引搜索更多的行。
2)、Not exists
MySQL能夠對查詢進行LEFT JOIN優化,發現1個匹配LEFT JOIN標準的行後,不再為前面的索引在該表內檢查更多的行。如下圖:
3)、Using filesort
MySQL 對數據使用一個外部的文件內容進行了排序,而不是按照表內的索引進行排序讀取。如下圖:
4)、Using index
僅使用索引樹中的信息從表中檢索列信息,而不必另外尋找讀取實際行,即不需要回表。如下圖:
5)、Using temporyary
在查詢時,MySQL需要創建一個臨時表來保存結果。常出現使用GROUP BY和ORDER BY子句時。如下圖:
6)、Using where
在查找使用索引的情況下,需要回表去查詢所需的數據,後再用WHERE子句完成結果過濾,通常出現這種情況的話就需要添加合適的索引來做優化了。如下圖:
7)、Using join buffer
連接中的表分成幾部分讀入連接緩衝區,然後從緩衝區中使用它們的行來與當前表執行連接。如下圖:
這次的內容就到這裡,歡迎大家在評論區評論!