mysql explain usage and meaning of results

The explain shows how MySQL uses indexes to process select statements and join tables. Can help choose better indexes and write more optimized query statements.

To use it, just add explain before the select statement:

Such as:

explain select surname,first_name form a,b where a.id=b.id 

Explanation of EXPLAIN column:

table: Displays which table the data of this row is about

type: This is the important column, showing what type of connection is used. The join types from best to worst are const, eq_reg, ref, range, index, and ALL

type shows the access type, which is a more important indicator. The result values ​​from good to bad are:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
Generally speaking, it is necessary to ensure that the query reaches at least the range level, preferably ref.

possible_keys: Displays the indexes that may be applied to this table. If empty, there are no possible indices. An appropriate statement can be selected from the WHERE statement for the relevant field

key: The actual index used. If NULL, no index is used. In rare cases, MYSQL will choose an index that is under-optimized. In this case, you can use USE INDEX(indexname) in the SELECT statement to force the use of an index or IGNORE INDEX(indexname) to force MySQL to ignore the index

key_len: The length of the index used. Shorter lengths are better without loss of accuracy

ref: shows which column of the index is used, a constant if possible

rows: The number of rows that MYSQL thinks must be checked to return the requested data

Extra: Extra information about how MYSQL parses the query. Will be discussed in table 4.3, bad examples that can be seen here are Using temporary and Using filesort, meaning MYSQL can't use indexes at all, the result is that retrieval will be slow

The meaning of the description returned by the extra column

 Distinct: Once MYSQL finds a row that matches the row union, no more searches

 Not exists: MYSQL optimizes LEFT JOIN, once it finds a row that matches the LEFT JOIN criteria, it doesn't search anymore

 Range checked for each Record (index map: #): The ideal index was not found, so for each combination of rows from the previous table, MYSQL checks which index is used and uses it to return rows from the table. This is one of the slowest connections using indexes

 Using filesort: When you see this, the query needs to be optimized. MYSQL takes an extra step to discover how to sort the returned rows. It sorts all rows based on the join type and the row pointer that stores the sort key value and all rows matching the criteria

 Using index: Column data is returned from a table that only uses the information in the index without the actual read action, which occurs when all requested columns for the table are part of the same index

 Using temporary When you see this, the query needs to be optimized. Here, MYSQL needs to create a temporary table to store the results, which usually happens on ORDER BY on different sets of columns, not on GROUP BY

 Where used uses a WHERE clause to limit which rows will be matched to the next table or returned to the user. This can happen if you don't want to return all the rows in the table, and if the join type is ALL or index, or if the query has a problem explaining the different join types (sorted in order of efficiency)

 The system table has only one row: the system table. This is a special case of const connection types

 const: The maximum value of a record in the table that can match this query (the index can be a primary key or a unique index). Because there is only one row, this value is actually a constant, because MYSQL reads the value first and treats it as a constant

 eq_ref: In the connection, MYSQL reads a record from the table for each record union from the previous table when querying, which is used when the query uses the index as the primary key or all of the unique key.

 ref: This join type only occurs when the query uses keys that are not unique or primary keys, or parts of these types (eg, using the leftmost prefix). For each row union of the previous table, all records will be read from the table. This type is heavily dependent on how many records are matched based on the index - fewer is better

 range: This join type returns the rows in a range using an index, as happens when using > or < to find something

 index: This join type performs a full scan of each record union in the preceding table (better than ALL, because the index is generally smaller than the table data)

 ALL: This join type performs a full scan of each preceding record union, which is generally bad and should be avoided as much as possible

  

Let's look at an example:

mysql> explain select * from t_order; 
+----+-------------+---------+------+---------------+------+---------+------+--------+-------+ 
| 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) 

After adding extended:

mysql> explain extended select * from t_order; 
+----+-------------+---------+------+---------------+------+---------+------+--------+----------+-------+ 
| 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) 

It is necessary to explain the meaning of each column in this long table:

id SELECT identifier. This is the query sequence number of the SELECT
select_type

SELECT type, which can be any of the following:

  • SIMPLE : Simple SELECT (without using UNION or subqueries)
  • PRIMARY : the outermost SELECT
  • UNION : The second or subsequent SELECT statement in UNION
  • DEPENDENT UNION : The second or subsequent SELECT statement in the UNION, depending on the outer query
  • UNION RESULT : result of UNION
  • SUBQUERY : The first SELECT in a subquery
  • DEPENDENT SUBQUERY : The first SELECT in a subquery, depending on the outer query
  • DERIVED : SELECT of the derived table (subquery of the FROM clause)
table

the table referenced by the output row

type

Join type. The various join types are given below, ordered from best to worst:

  • system : The table has only one row (=system table). This is a special case of the const join type.
  • const : The table has at most one matching row, which will be read at the start of the query. Since there is only one row, the column values ​​in this row can be considered constant by the rest of the optimizer. const tables are fast because they are only read once!
  • eq_ref : For each combination of rows from the preceding table, read a row from this table. This is probably the best join type, except for const types.
  • ref : For each combination of rows from the preceding table, all rows with matching index values ​​will be read from this table.
  • ref_or_null : This join type is like ref, but with the addition that MySQL can specifically search for rows containing NULL values.
  • index_merge : This join type indicates that the index merge optimization method is used.
  • unique_subquery : This type replaces the ref of the IN subquery of the following form: value IN (SELECT primary_key FROM single_table WHERE some_expr) unique_subquery is an indexed lookup function that can completely replace subqueries with higher efficiency.
  • index_subquery : This join type is similar to unique_subquery. IN subqueries can be replaced, but only for non-unique indexes in subqueries of the form: value IN (SELECT key_column FROM single_table WHERE some_expr)
  • range : Retrieve only a given range of rows, using an index to select rows.
  • index : This join type is the same as ALL, except that only the index tree is scanned. This is usually faster than ALL because index files are usually smaller than data files.
  • ALL : For each combination of rows from the previous table, perform a full table scan.
possible_keys

Indicates which index MySQL can use to find rows in this table

key Shows the keys (indexes) that MySQL actually decided to use. If no index is selected, the key is NULL.
key_len Displays the key length that MySQL decided to use. If the key is NULL, the length is NULL.
ref Shows which column or constant is used with key to select rows from the table.
rows Displays the number of rows that MySQL thinks it must examine when executing the query. Multiplying data across multiple rows gives an estimate of the number of rows to process.
filtered Shows a percentage estimate of the number of rows filtered by the criteria.
Extra

This column contains the details of the query being resolved by MySQL

  • Distinct : MySQL stops searching for more rows for the current row combination after finding the first matching row.
  • Not exists : MySQL can perform LEFT JOIN optimization on the query. After finding a row that matches the LEFT JOIN criteria, it will not check more rows in the table for the previous row combination.
  • range checked for each record (index map: #) : MySQL did not find a good index to use, but found that if the column value from the previous table is known, maybe a partial index can be used.
  • Using filesort:MySQL需要额外的一次传递,以找出如何按排序顺序检索行。
  • Using index:从只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。
  • Using temporary:为了解决查询,MySQL需要创建一个临时表来容纳结果。
  • Using where:WHERE 子句用于限制哪一个行匹配下一个表或发送到客户。
  • Using sort_union(...), Using union(...), Using intersect(...):这些函数说明如何为index_merge联接类型合并索引扫描。
  • Using index for group-by:类似于访问表的Using index方式,Using index for group-by表示MySQL发现了一个索引,可以用来查 询GROUP BY或DISTINCT查询的所有列,而不要额外搜索硬盘访问实际的表。

 

一.select_type的说明

1.UNION:

当通过union来连接多个查询结果时,第二个之后的select其select_type为UNION。

mysql> explain select * from t_order where order_id=100 union select * from t_order where order_id=200; 
+----+--------------+------------+-------+---------------+---------+---------+-------+------+-------+ 
| 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 | <union1,2> | ALL   | NULL          | NULL    | NULL    | NULL  | NULL |       | 
+----+--------------+------------+-------+---------------+---------+---------+-------+------+-------+ 
3 rows in set (0.34 sec) 

2.DEPENDENT UNION与DEPENDENT SUBQUERY:

当union作为子查询时,其中第二个union的select_type就是DEPENDENT UNION。
第一个子查询的select_type则是DEPENDENT SUBQUERY。

mysql> explain select * from t_order where order_id in (select order_id from t_order where order_id=100 union select order_id from t_order where order_id=200); 
+----+--------------------+------------+-------+---------------+---------+---------+-------+--------+-------------+ 
| 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       | <union2,3> | ALL   | NULL          | NULL    | NULL    | NULL  |   NULL |             | 
+----+--------------------+------------+-------+---------------+---------+---------+-------+--------+-------------+ 
4 rows in set (0.03 sec) 

3.SUBQUERY:

子查询中的第一个select其select_type为SUBQUERY。

mysql> explain select * from t_order where order_id=(select order_id from t_order where order_id=100); 
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+ 
| 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> explain select * from (select order_id from t_order where order_id=100) a; 
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+ 
| id | select_type | table      | type   | possible_keys | key     | key_len | ref  | rows | Extra       | 
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+ 
|  1 | PRIMARY     | <derived2> | system | NULL          | NULL    | NULL    | NULL |    1 |             | 
|  2 | DERIVED     | t_order    | const  | PRIMARY       | PRIMARY | 4       |      |    1 | Using index | 
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+ 
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> explain select * from t_order a,t_order_ext b where a.order_id=b.order_id; 
+----+-------------+-------+--------+---------------+---------+---------+-----------------+------+-------------+ 
| 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> explain select * from t_order a,t_order_ext b where a.order_id=b.order_id and a.order_id=100; 
+----+-------------+-------+-------+---------------+----------+---------+-------+------+-------+ 
| 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> explain select * from t_order where user_id=100 or user_id is null; 
+----+-------------+---------+-------------+---------------+---------+---------+-------+-------+-------------+ 
| 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> explain select * from t_order where order_id=100 or user_id=10; 
+----+-------------+---------+-------------+-----------------+-----------------+---------+------+------+-------------------------------------------+ 
| 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> explain select * from t_order where order_id in (select order_id from t_order where user_id=10); 
+----+--------------------+---------+-----------------+-----------------+---------+---------+------+--------+-------------+ 
| 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> explain select * from t_order where user_id in (select user_id from t_order where order_id>10); 
+----+--------------------+---------+----------------+-----------------+---------+---------+------+--------+--------------------------+ 
| 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> explain select * from t_order where user_id in (100,200,300); 
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+ 
| 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> explain select count(*) from t_order; 
+----+-------------+---------+-------+---------------+---------+---------+------+--------+-------------+ 
| 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> explain select * from t_order; 
+----+-------------+---------+------+---------------+------+---------+------+--------+-------+ 
| 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> explain select count(1) from t_order a left join t_order_ext b on a.order_id=b.order_id where b.order_id is null;  
+----+-------------+-------+-------+---------------+--------------+---------+-----------------+--------+--------------------------------------+ 
| 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> explain select * from t_order t, t_order_ext s where s.order_id>=t.order_id and s.order_id<=t.order_id and t.express_type>5; 
+----+-------------+-------+-------+----------------------+--------------+---------+------+------+------------------------------------------------+ 
| 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> explain select * from t_order order by express_type; 
+----+-------------+---------+------+---------------+------+---------+------+--------+----------------+ 
| 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> explain select * from t_order a left join t_order_ext b on a.order_id=b.order_id group by b.order_id; 
+----+-------------+-------+------+---------------+----------+---------+-----------------+--------+---------------------------------+ 
| 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> explain select * from t_order where order_id=100 or user_id>10; 
+----+-------------+---------+-------------+-----------------+-----------------+---------+------+------+------------------------------------------------+ 
| 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> explain select * from t_order where express_type=1 and user_id=100; 
+----+-------------+---------+-------------+----------------------+----------------------+---------+------+------+----------------------------------------------------+ 
| 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> explain select user_id from t_order group by user_id; 
+----+-------------+---------+-------+---------------+---------+---------+------+------+--------------------------+ 
| 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) 

除了上面的三个说明,还需要注意rows的数值,多行之间的数值是乘积的关系,可以估算大概要处理的行数,如果乘积很大,那就很有优化的必要了。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325587362&siteId=291194637