本文轉載自最官方的 mysql explain type 字段解讀
讀了很多別人的筆記都雜亂不堪,很少有實例,什么都不如原裝的好,所以當你讀到我的筆記的時候如果覺得說的不明白,最好參考官方的手冊。
我把官方的手冊簡單翻譯了下,好多地方也還是不懂,網友補充,配合了官方的實例代碼
更多請更多的參考 https://dev.mysql.com/doc/refman/5.6/en/explain-output.html#explain-join-types
下面的筆記是根據我自己的 mysql 服務的版本號來的
mysql> select version();
+------------+
| version() |
+------------+
| 5.6.16-log |
+------------+
1 row in set (0.00 sec)
隨便放一個查詢結果,我們要說的就是這里的type
的值。
mysql> explain SELECT id,title FROM seo_php_article where is_delete=0 order by id asc limit 66500,500;
+----+-------------+-----------------+------+---------------+-----------+---------+-------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------+------+---------------+-----------+---------+-------+-------+-----------------------------+
| 1 | SIMPLE | seo_php_article | ref | is_delete | is_delete | 1 | const | 67500 | Using where; Using filesort |
+----+-------------+-----------------+------+---------------+-----------+---------+-------+-------+-----------------------------+
1 row in set (0.00 sec)
The type column of EXPLAIN output describes how tables are joined. The following list describes the join types, ordered from the best type to the worst:
下面的從好到壞依次解釋:
system
The table has only one row (= system table). This is a special case of the const join type.
觸發條件:表只有一行,這是一個const
type 的特殊情況。
const
The table has at most one matching row, which is read at the start of the query. Because there is only one row, values from the column in this row can be regarded as constants by the rest of the optimizer. const tables are very fast because they are read only once.
觸發條件:最多只有一行匹配。
const
is used when you compare all parts of aPRIMARY KEY
orUNIQUE
index to constant values. In the following queries,tbl_name
can be used as a const table:
當你使用主鍵或者唯一索引的時候,就是const
類型,比如下面這兩種查詢
# 單一主鍵
SELECT * FROM tbl_name WHERE primary_key=1;
# 聯合主鍵
SELECT * FROM tbl_name WHERE primary_key_part1=1 AND primary_key_part2=2;
eq_ref
One row is read from this table for each combination of rows from the previous tables. Other than the system and const types, this is the best possible join type. It is used when all parts of an index are used by the join and the index is a PRIMARY KEY or UNIQUE NOT NULL index.
觸發條件:只匹配到一行的時候。除了system
和const
之外,這是最好的連接類型了。當我們使用主鍵索引或者唯一索引的時候,且這個索引的所有組成部分都被用上,才能是該類型。
eq_ref can be used for indexed columns that are compared using the = operator. The comparison value can be a constant or an expression that uses columns from tables that are read before this table. In the following examples, MySQL can use an eq_ref join to process ref_table
在對已經建立索引列進行=
操作的時候,eq_ref
會被使用到。比較值可以使用一個常量也可以是一個表達式。這個表達示可以是其他的表的行。
# 多表關聯查詢,單行匹配
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;
# 多表關聯查詢,聯合索引,多行匹配
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;
ref
All rows with matching index values are read from this table for each combination of rows from the previous tables. ref is used if the join uses only a leftmost prefix of the key or if the key is not a PRIMARY KEY or UNIQUE index (in other words, if the join cannot select a single row based on the key value). If the key that is used matches only a few rows, this is a good join type.
第一句沒理解透,先理解到多行匹配吧。
觸發條件:觸發聯合索引最左原則(不知道的搜下),或者這個索引不是主鍵,也不是唯一索引(換句話說,如果這個在這個索引基礎之上查詢的結果多於一行)。
如果使用那個索引只匹配到非常少的行,也是不錯的。
ref can be used for indexed columns that are compared using the = or <=> operator. In the following examples, MySQL can use a ref join to process ref_table:
在對已經建立索引列進行=
或者<=>
操作的時候,ref
會被使用到。與eq_ref
不同的是匹配到了多行
# 根據索引(非主鍵,非唯一索引),匹配到多行
SELECT * FROM ref_table WHERE key_column=expr;
# 多表關聯查詢,單個索引,多行匹配
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;
# 多表關聯查詢,聯合索引,多行匹配
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;
fulltext
The join is performed using a FULLTEXT index.
使用全文索引的時候才會出現
ref_or_null
This join type is like ref, but with the addition that MySQL does an extra search for rows that contain NULL values. This join type optimization is used most often in resolving subqueries. In the following examples, MySQL can use a ref_or_null join to process ref_table:
這個查詢類型和ref
很像,但是 MySQL 會做一個額外的查詢,來看哪些行包含了NULL
。這種類型常見於解析子查詢的優化。(我理解為 mysql 自己做的優化)
SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;
index_merge
This join type indicates that the Index Merge optimization is used. In this case, the key column in the output row contains a list of indexes used, and key_len contains a list of the longest key parts for the indexes used. For more information, see Section 8.2.1.3, “Index Merge Optimization”.
在一個查詢里面很有多索引用被用到,可能會觸發index_merge
的優化機制。
unique_subquery
This type replaces eq_ref for some IN subqueries of the following form:
比eq_ref
復雜的地方是使用了in
的子查詢,而且是子查詢是主鍵或者唯一索引
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery is just an index lookup function that replaces the subquery completely for better efficiency.
unique_subquery
只是一個索引查找函數,它可以完全替代子查詢以提高效率。明白,現在不就是在做子查詢嗎?
index_subquery
This join type is similar to unique_subquery. It replaces IN subqueries, but it works for nonunique indexes in subqueries of the following form:
它和unique_subquery
,但是它在子查詢里使用的是非唯一索引。
value IN (SELECT key_column FROM single_table WHERE some_expr)
range
Only rows that are in a given range are retrieved, using an index to select the rows. The key column in the output row indicates which index is used. The key_len contains the longest key part that was used. The ref column is NULL for this type.
只有給定范圍內的行才能被檢索,使用索引來查詢出多行。 輸出行中的類決定了會使用哪個索引。 key_len
列表示使用的最長的 key 部分。 這個類型的ref
列是NULL。
range can be used when a key column is compared to a constant using any of the =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, or IN() operators:
# 常量比較,可能多行(但是這里的例子和上面 ref 的第一個例子不一樣嗎?)
SELECT * FROM tbl_name
WHERE key_column = 10;
# 范圍查找
SELECT * FROM tbl_name
WHERE key_column BETWEEN 10 and 20;
# 范圍查找
SELECT * FROM tbl_name
WHERE key_column IN (10,20,30);
# 多條件加范圍查找
SELECT * FROM tbl_name
WHERE key_part1 = 10 AND key_part2 IN (10,20,30);
index
The index join type is the same as ALL, except that the index tree is scanned. This occurs two ways:
- If the index is a covering index for the queries and can be used to satisfy all data required from the table, only the index tree is scanned. In this case, the Extra column says Using index. An index-only scan usually is faster than ALL because the size of the index usually is smaller than the table data.
- A full table scan is performed using reads from the index to look up data rows in index order. Uses index does not appear in the Extra column.
index
類型和ALL
類型一樣,區別就是index
類型是掃描的索引樹。以下兩種情況會觸發:
- 如果索引是查詢的覆蓋索引,就是說索引查詢的數據可以滿足查詢中所需的所有數據,則只掃描索引樹,不需要回表查詢。 在這種情況下,explain 的
Extra
列的結果是Using index
。僅索引掃描通常比ALL快,因為索引的大小通常小於表數據。 - 全表掃描會按索引的順序來查找數據行。使用索引不會出現在
Extra
列中。
ALL
A full table scan is done for each combination of rows from the previous tables. This is normally not good if the table is the first table not marked const, and usually very bad in all other cases. Normally, you can avoid ALL by adding indexes that enable row retrieval from the table based on constant values or column values from earlier tables.
全表掃描就不用看了,趕快優化吧。