您好,登錄后才能下訂單哦!
本篇文章為大家展示了mysql 中如何使用explain,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
重點是第二種用法,需要深入的了解。
先看一個例子:
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+--------+-------+
| 1 | SIMPLE | t_order | ALL | NULL | NULL | NULL | NULL | 100453 | |
+----+-------------+---------+------+---------------+------+---------+------+--------+-------+
1 row in set (0.03 sec)
加上extended后之后:
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------+---------------+------+---------+------+--------+----------+-------+
| 1 | SIMPLE | t_order | ALL | NULL | NULL | NULL | NULL | 100453 | 100.00 | |
+----+-------------+---------+------+---------------+------+---------+------+--------+----------+-------+
1 row in set, 1 warning (0.00 sec)
有必要解釋一下這個長長的表格里每一列的含義:
id | SELECT識別符。這是SELECT的查詢序列號 |
select_type | SELECT類型,可以為以下任何一種:
|
table | 輸出的行所引用的表 |
type | 聯接類型。下面給出各種聯接類型,按照從最佳類型到最壞類型進行排序:
|
possible_keys | 指出MySQL能使用哪個索引在該表中找到行 |
key | 顯示MySQL實際決定使用的鍵(索引)。如果沒有選擇索引,鍵是NULL。 |
key_len | 顯示MySQL決定使用的鍵長度。如果鍵是NULL,則長度為NULL。 |
ref | 顯示使用哪個列或常數與key一起從表中選擇行。 |
rows | 顯示MySQL認為它執行查詢時必須檢查的行數。多行之間的數據相乘可以估算要處理的行數。 |
filtered | 顯示了通過條件過濾出的行數的百分比估計值。 |
Extra | 該列包含MySQL解決查詢的詳細信息
|
一.select_type的說明
1.UNION:
當通過union來連接多個查詢結果時,第二個之后的select其select_type為UNION。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+------------+-------+---------------+---------+---------+-------+------+-------+
| 1 | PRIMARY | t_order | const | PRIMARY | PRIMARY | 4 | const | 1 | |
| 2 | UNION | t_order | const | PRIMARY | PRIMARY | 4 | const | 1 | |
| NULL | UNION RESULT | 3 rows in set (0.34 sec)
2.DEPENDENT UNION與DEPENDENT SUBQUERY:
當union作為子查詢時,其中第二個union的select_type就是DEPENDENT UNION。
第一個子查詢的select_type則是DEPENDENT SUBQUERY。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+-------+---------------+---------+---------+-------+--------+-------------+
| 1 | PRIMARY | t_order | ALL | NULL | NULL | NULL | NULL | 100453 | Using where |
| 2 | DEPENDENT SUBQUERY | t_order | const | PRIMARY | PRIMARY | 4 | const | 1 | Using index |
| 3 | DEPENDENT UNION | t_order | const | PRIMARY | PRIMARY | 4 | const | 1 | Using index |
| NULL | UNION RESULT | +----+--------------------+------------+-------+---------------+---------+---------+-------+--------+-------------+
4 rows in set (0.03 sec)
3.SUBQUERY:
子查詢中的第一個select其select_type為SUBQUERY。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+
| 1 | PRIMARY | t_order | const | PRIMARY | PRIMARY | 4 | const | 1 | |
| 2 | SUBQUERY | t_order | const | PRIMARY | PRIMARY | 4 | | 1 | Using index |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+
2 rows in set (0.03 sec)
4.DERIVED:
當子查詢是from子句時,其select_type為DERIVED。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+
| 1 | PRIMARY | +----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+
2 rows in set (0.03 sec)
二.type的說明
1.system,const
見上面4.DERIVED的例子。其中第一行的type就是為system,第二行是const,這兩種聯接類型是最快的。
2.eq_ref
在t_order表中的order_id是主鍵,t_order_ext表中的order_id也是主鍵,該表可以認為是訂單表的補充信息表,他們的關系是1對1,在下面的例子中可以看到b表的連接類型是eq_ref,這是極快的聯接類型。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+-----------------+------+-------------+
| 1 | SIMPLE | b | ALL | order_id | NULL | NULL | NULL | 1 | |
| 1 | SIMPLE | a | eq_ref | PRIMARY | PRIMARY | 4 | test.b.order_id | 1 | Using where |
+----+-------------+-------+--------+---------------+---------+---------+-----------------+------+-------------+
2 rows in set (0.00 sec)
3.ref
下面的例子在上面的例子上略作了修改,加上了條件。此時b表的聯接類型變成了ref。因為所有與a表中order_id=100的匹配記錄都將會從b表獲取。這是比較常見的聯接類型。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+----------+---------+-------+------+-------+
| 1 | SIMPLE | a | const | PRIMARY | PRIMARY | 4 | const | 1 | |
| 1 | SIMPLE | b | ref | order_id | order_id | 4 | const | 1 | |
+----+-------------+-------+-------+---------------+----------+---------+-------+------+-------+
2 rows in set (0.00 sec)
4.ref_or_null
user_id字段是一個可以為空的字段,并對該字段創建了一個索引。在下面的查詢中可以看到聯接類型為ref_or_null,這是mysql為含有null的字段專門做的處理。在我們的表設計中應當盡量避免索引字段為NULL,因為這會額外的耗費mysql的處理時間來做優化。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------------+---------------+---------+---------+-------+-------+-------------+
| 1 | SIMPLE | t_order | ref_or_null | user_id | user_id | 5 | const | 50325 | Using where |
+----+-------------+---------+-------------+---------------+---------+---------+-------+-------+-------------+
1 row in set (0.00 sec)
5.index_merge
經常出現在使用一張表中的多個索引時。mysql會將多個索引合并在一起,如下例:
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------------+-----------------+-----------------+---------+------+------+-------------------------------------------+
| 1 | SIMPLE | t_order | index_merge | PRIMARY,user_id | PRIMARY,user_id | 4,5 | NULL | 2 | Using union(PRIMARY,user_id); Using where |
+----+-------------+---------+-------------+-----------------+-----------------+---------+------+------+-------------------------------------------+
1 row in set (0.09 sec)
6.unique_subquery
該聯接類型用于替換value IN (SELECT primary_key FROM single_table WHERE some_expr)這樣的子查詢的ref。注意ref列,其中第二行顯示的是func,表明unique_subquery是一個函數,而不是一個普通的ref。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+---------+-----------------+-----------------+---------+---------+------+--------+-------------+
| 1 | PRIMARY | t_order | ALL | NULL | NULL | NULL | NULL | 100649 | Using where |
| 2 | DEPENDENT SUBQUERY | t_order | unique_subquery | PRIMARY,user_id | PRIMARY | 4 | func | 1 | Using where |
+----+--------------------+---------+-----------------+-----------------+---------+---------+------+--------+-------------+
2 rows in set (0.00 sec)
7.index_subquery
該聯接類型與上面的太像了,唯一的差別就是子查詢查的不是主鍵而是非唯一索引。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+---------+----------------+-----------------+---------+---------+------+--------+--------------------------+
| 1 | PRIMARY | t_order | ALL | NULL | NULL | NULL | NULL | 100649 | Using where |
| 2 | DEPENDENT SUBQUERY | t_order | index_subquery | PRIMARY,user_id | user_id | 5 | func | 50324 | Using index; Using where |
+----+--------------------+---------+----------------+-----------------+---------+---------+------+--------+--------------------------+
2 rows in set (0.00 sec)
8.range
按指定的范圍進行檢索,很常見。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | t_order | range | user_id | user_id | 5 | NULL | 3 | Using where |
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)
9.index
在進行統計時非常常見,此聯接類型實際上會掃描索引樹,僅比ALL快些。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+------+--------+-------------+
| 1 | SIMPLE | t_order | index | NULL | user_id | 5 | NULL | 100649 | Using index |
+----+-------------+---------+-------+---------------+---------+---------+------+--------+-------------+
1 row in set (0.00 sec)
10.ALL
完整的掃描全表,最慢的聯接類型,盡可能的避免。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+--------+-------+
| 1 | SIMPLE | t_order | ALL | NULL | NULL | NULL | NULL | 100649 | |
+----+-------------+---------+------+---------------+------+---------+------+--------+-------+
1 row in set (0.00 sec)
三.extra的說明
1.Distinct
MySQL發現第1個匹配行后,停止為當前的行組合搜索更多的行。對于此項沒有找到合適的例子,求指點。
2.Not exists
因為b表中的order_id是主鍵,不可能為NULL,所以mysql在用a表的order_id掃描t_order表,并查找b表的行時,如果在b表發現一個匹配的行就不再繼續掃描b了,因為b表中的order_id字段不可能為NULL。這樣避免了對b表的多次掃描。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+--------------+---------+-----------------+--------+--------------------------------------+
| 1 | SIMPLE | a | index | NULL | express_type | 1 | NULL | 100395 | Using index |
| 1 | SIMPLE | b | ref | order_id | order_id | 4 | test.a.order_id | 1 | Using where; Using index; Not exists |
+----+-------------+-------+-------+---------------+--------------+---------+-----------------+--------+--------------------------------------+
2 rows in set (0.01 sec)
3.Range checked for each record
這種情況是mysql沒有發現好的索引可用,速度比沒有索引要快得多。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+----------------------+--------------+---------+------+------+------------------------------------------------+
| 1 | SIMPLE | t | range | PRIMARY,express_type | express_type | 1 | NULL | 1 | Using where |
| 1 | SIMPLE | s | ALL | order_id | NULL | NULL | NULL | 1 | Range checked for each record (index map: 0x1) |
+----+-------------+-------+-------+----------------------+--------------+---------+------+------+------------------------------------------------+
2 rows in set (0.00 sec)
4.Using filesort
在有排序子句的情況下很常見的一種情況。此時mysql會根據聯接類型瀏覽所有符合條件的記錄,并保存排序關鍵字和行指針,然后排序關鍵字并按順序檢索行。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+--------+----------------+
| 1 | SIMPLE | t_order | ALL | NULL | NULL | NULL | NULL | 100395 | Using filesort |
+----+-------------+---------+------+---------------+------+---------+------+--------+----------------+
1 row in set (0.00 sec)
5.Using index
這是性能很高的一種情況。當查詢所需的數據可以直接從索引樹中檢索到時,就會出現。上面的例子中有很多這樣的例子,不再多舉例了。
6.Using temporary
發生這種情況一般都是需要進行優化的。mysql需要創建一張臨時表用來處理此類查詢。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+----------+---------+-----------------+--------+---------------------------------+
| 1 | SIMPLE | a | ALL | NULL | NULL | NULL | NULL | 100395 | Using temporary; Using filesort |
| 1 | SIMPLE | b | ref | order_id | order_id | 4 | test.a.order_id | 1 | |
+----+-------------+-------+------+---------------+----------+---------+-----------------+--------+---------------------------------+
2 rows in set (0.00 sec)
7.Using where
當有where子句時,extra都會有說明。
8.Using sort_union(...)/Using union(...)/Using intersect(...)
下面的例子中user_id是一個檢索范圍,此時mysql會使用sort_union函數來進行索引的合并。而當user_id是一個固定值時,請參看上面type說明5.index_merge的例子,此時會使用union函數進行索引合并。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------------+-----------------+-----------------+---------+------+------+------------------------------------------------+
| 1 | SIMPLE | t_order | index_merge | PRIMARY,user_id | user_id,PRIMARY | 5,4 | NULL | 2 | Using sort_union(user_id,PRIMARY); Using where |
+----+-------------+---------+-------------+-----------------+-----------------+---------+------+------+------------------------------------------------+
1 row in set (0.00 sec)
對于Using intersect的例子可以參看下例,user_id與express_type發生了索引交叉合并。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------------+----------------------+----------------------+---------+------+------+----------------------------------------------------+
| 1 | SIMPLE | t_order | index_merge | user_id,express_type | user_id,express_type | 5,1 | NULL | 1 | Using intersect(user_id,express_type); Using where |
+----+-------------+---------+-------------+----------------------+----------------------+---------+------+------+----------------------------------------------------+
1 row in set (0.00 sec)
9.Using index for group-by
表明可以在索引中找到分組所需的所有數據,不需要查詢實際的表。
mysql | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+------+------+--------------------------+
| 1 | SIMPLE | t_order | range | NULL | user_id | 5 | NULL | 3 | Using index for group-by |
+----+-------------+---------+-------+---------------+---------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
上述內容就是mysql 中如何使用explain,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。