MySQL Explain 详解

MySQL Explain 详解

实验环境

  • 操作系统:centos 7.4
  • 操作系统内核版本:3.10.0-693.el7.x86_64
  • MySQL数据库:5.7.20-log MySQL Community Server (GPL)
名词
QEP: Query Execution Plan,查询执行计划。
语法
EXPLAIN [ explain_type] { explainable_stmt }

explain_type:
{ EXTENDED | PARTITIONS | FORMAT = format_name}

format_name:
{ TRADITIONAL | JSON}
explainable_stmt:
{ SELECT statement | DELETE statement | INSERT statement | REPLACE statement | UPDATE statement }

EXPLAIN与DESCRIBE、DESC是同义词。实践中,通常EXPLAIN用于获取QEP,而DESCRIBE、DESC用于获取表结构信息。

explain_type中,EXTENDED和PARTITIONS 可不写,默认会输出这两列的信息。如:

mysql> explain select * from users where userid=1;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | users | NULL       | const | PRIMARY       | PRIMARY | 8       | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

format_name中TRADITIONAL表示输出格式跟上面一样的表格输出,默认此输出格式。JSON表示输出为json格式,如:

mysql> explain format=json select * from users where userid=1\G
*************************** 1. row ***************************
EXPLAIN: {
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "1.00"
    },
    "table": {
      "table_name": "users",
      "access_type": "const",
      "possible_keys": [
        "PRIMARY"
      ],
      "key": "PRIMARY",
      "used_key_parts": [
        "userid"
      ],
      "key_length": "8",
      "ref": [
        "const"
      ],
      "rows_examined_per_scan": 1,
      "rows_produced_per_join": 1,
      "filtered": "100.00",
      "cost_info": {
        "read_cost": "0.00",
        "eval_cost": "0.20",
        "prefix_cost": "0.00",
        "data_read_per_join": "2K"
      },
      "used_columns": [
        "userid",
        "alias",
        "name",
        "surname",
        "passwd",
        "url",
        "autologin",
        "autologout",
        "lang",
        "refresh",
        "type",
        "theme",
        "attempt_failed",
        "attempt_ip",
        "attempt_clock",
        "rows_per_page"
      ]
    }
  }
}
1 row in set, 1 warning (0.00 sec)

除SELECT语句外,EXPLAIN还可直接获取DELETE/UPDATE/INSERT/REPLACE语句的QEP而无需改写为SELECT语句。如:

mysql> explain delete from users where userid=1;  
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
|  1 | DELETE      | users | NULL       | range | PRIMARY       | PRIMARY | 8       | const |    1 |   100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
1 row in set (0.00 sec)
mysql> explain update users set name='test' where userid=1;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
|  1 | UPDATE      | users | NULL       | range | PRIMARY       | PRIMARY | 8       | const |    1 |   100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
1 row in set (0.00 sec)
mysql> explain insert into usrgrp values(1,'test',0,0,0);
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | INSERT      | usrgrp | NULL       | ALL  | NULL          | NULL | NULL    | NULL | NULL |     NULL | NULL  |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set (0.00 sec)
mysql> explain replace into usrgrp values(1,'test',0,0,0);
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | REPLACE     | usrgrp | NULL       | ALL  | NULL          | NULL | NULL    | NULL | NULL |     NULL | NULL  |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set (0.00 sec)

输出

输出列含义
id查询标识
select_type查询类型
table查询涉及的表
partitions匹配到的分区信息
type连接类型
possible_keys可能选择的索引
key实际使用的索引
key_len实际使用的索引的长度
ref和索引进行比较的列
rows需要被检索的大致行数
filtered按表条件过滤的行百分比
Extra额外信息

id:

查询标识,查询语句的序号。
表示查询中执行select子句或操作表的顺序

id相同,执行顺序由上至下:
mysql> explain select * from users t1,users_groups t2 where t1.userid = t2.userid;
+----+-------------+-------+------------+------+----------------+----------------+---------+------------------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys  | key            | key_len | ref              | rows | filtered | Extra |
+----+-------------+-------+------------+------+----------------+----------------+---------+------------------+------+----------+-------+
|  1 | SIMPLE      | t1    | NULL       | ALL  | PRIMARY        | NULL           | NULL    | NULL             |    7 |   100.00 | NULL  |
|  1 | SIMPLE      | t2    | NULL       | ref  | users_groups_2 | users_groups_2 | 8       | zabbix.t1.userid |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+----------------+----------------+---------+------------------+------+----------+-------+
2 rows in set, 1 warning (0.00 sec)

如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行:
mysql> explain select * from users where userid = (select userid from users_groups where id=4);
+----+-------------+--------------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table        | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+--------------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | PRIMARY     | users        | NULL       | const | PRIMARY       | PRIMARY | 8       | const |    1 |   100.00 | NULL  |
|  2 | SUBQUERY    | users_groups | NULL       | const | PRIMARY       | PRIMARY | 8       | const |    1 |   100.00 | NULL  |
+----+-------------+--------------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
2 rows in set, 1 warning (0.00 sec)

id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行:
mysql> explain select * from users where userid in (select userid from users_groups);
+----+--------------+--------------+------------+--------+----------------+----------------+---------+---------------------+------+----------+-------------+
| id | select_type  | table        | partitions | type   | possible_keys  | key            | key_len | ref                 | rows | filtered | Extra       |
+----+--------------+--------------+------------+--------+----------------+----------------+---------+---------------------+------+----------+-------------+
|  1 | SIMPLE       | users        | NULL       | ALL    | PRIMARY        | NULL           | NULL    | NULL                |    7 |   100.00 | Using where |
|  1 | SIMPLE       | <subquery2>  | NULL       | eq_ref | <auto_key>     | <auto_key>     | 8       | zabbix.users.userid |    1 |   100.00 | NULL        |
|  2 | MATERIALIZED | users_groups | NULL       | index  | users_groups_2 | users_groups_2 | 8       | NULL                |    7 |   100.00 | Using index |
+----+--------------+--------------+------------+--------+----------------+----------------+---------+---------------------+------+----------+-------------+
3 rows in set, 1 warning (0.00 sec)

当该行数据引用了其它查询的UNION结果时,id列显示为NULL,此时,table列显示类似这样:< unionM,N>,表示引用了查询标识为M、N的两行的UNION结果。如:

mysql> explain select userid from users where userid=1 union select usrgrpid userid from usrgrp where usrgrpid=7;
+----+--------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-----------------+
| id | select_type  | table      | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra           |
+----+--------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-----------------+
|  1 | PRIMARY      | users      | NULL       | const | PRIMARY       | PRIMARY | 8       | const |    1 |   100.00 | Using index     |
|  2 | UNION        | usrgrp     | NULL       | const | PRIMARY       | PRIMARY | 8       | const |    1 |   100.00 | Using index     |
| NULL | UNION RESULT | <union1,2> | NULL       | ALL   | NULL          | NULL    | NULL    | NULL  | NULL |     NULL | Using temporary |
+----+--------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-----------------+
3 rows in set, 1 warning (0.00 sec)

select_type
查询类型。

查询类型含义
SIMPLE简单查询(不包含子查询或UNION)
PRIMARY最外层查询
UNIONUNION语句中第二或更后面的查询
DEPENDENT UNION依赖外部查询的UNION中第二或更后面的查询
UNION RESULTUNION语句的结果集
SUBQUERY子查询中的第一个查询
DEPENDENT SUBQUERY依赖外部查询的子查询中的第一个查询
DERIVED查询的派生表(在FROM从句中的子查询)
MATERIALIZED物化子查询
UNCACHEABLE SUBQUERY无法缓存结果的子查询,并且必须为外部查询的每一行重新计算
UNCACHEABLE UNION属于无法缓存的子查询的UNION的第二或更后面的查询

table
输出行引用的表的名称。这也可以是下列值之一:

< unionM,N>:输出行引用了id值为M和N的行的UNION结果。
< derivedN>:该行引用了一个id值为n的行的派生表结果。
例如,派生表可以从from子句的子查询中得到结果。
< subqueryN>:输出行引用了id值为N的行的物化子查询的结果

partitions
由查询匹配记录的分区。对于非分区表,值为NULL。

type
表示MySQL在表中找到所需行的方式,又称“访问类型”,常见类型从最好到最差依次如下:

system, const, eq_ref, ref, fulltext, ref_or_null, index_merge, unique_subquery, index_subquery, range, index, ALL


system
表只有一行记录,这是const类型的一种特殊情况。

mysql> explain select * from mysql.proxies_priv;
+----+-------------+--------------+------------+--------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table        | partitions | type   | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+--------------+------------+--------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | proxies_priv | NULL       | system | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL  |
+----+-------------+--------------+------------+--------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

const
常量查询。
在整个查询过程中,该表最多有一个匹配行,在查询开始时读取。
因为只有一行,所以这个行中的列值可以被其他优化器视为常量。const表非常快,因为它们只读一次。
当你将主键或唯一索引的所有部分与常量值进行比较时,将使用const。
例如:

mysql> explain select * from users where userid=1;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | users | NULL       | const | PRIMARY       | PRIMARY | 8       | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

eq_ref
对前面的表中每一行记录的组合,都从当前表中读取一行。
除了system和const类型之外,这是最好的连接类型。
主键或非空唯一索引在索引的所有部分都被join使用时采用。
eq_ref可用于与使用=操作符进行比较的索引列。
比较值可以是一个常量,也可以是一个在该表之前读取的表的列的表达式。

类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件。

mysql> explain select * from users_groups a ,usrgrp b where a.id = b.usrgrpid;
+----+-------------+-------+------------+--------+---------------+----------------+---------+-------------+------+----------+-------------+
| id | select_type | table | partitions | type   | possible_keys | key            | key_len | ref         | rows | filtered | Extra       |
+----+-------------+-------+------------+--------+---------------+----------------+---------+-------------+------+----------+-------------+
|  1 | SIMPLE      | a     | NULL       | index  | PRIMARY       | users_groups_1 | 16      | NULL        |    7 |   100.00 | Using index |
|  1 | SIMPLE      | b     | NULL       | eq_ref | PRIMARY       | PRIMARY        | 8       | zabbix.a.id |    1 |   100.00 | NULL        |
+----+-------------+-------+------------+--------+---------------+----------------+---------+-------------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

ref
对前面的表中每一行记录的组合,都从当前表中读取所有匹配索引值的行。
如果join仅使用key的最左前缀,或者key不是主键或唯一索引(换句话说,如果连接不能基于key值选择单个行),则使用ref。
如果使用的key只匹配几行,这是一个很好的连接类型。

简单来说,就是使用非唯一索引扫描或者唯一索引的前缀扫描,返回匹配某个单独值的记录行


mysql> explain select * from media a,media_type b where a.mediatypeid=b.mediatypeid and b.mediatypeid=1;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | b     | NULL       | const | PRIMARY       | PRIMARY | 8       | const |    1 |   100.00 | NULL  |
|  1 | SIMPLE      | a     | NULL       | ref   | media_2       | media_2 | 8       | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
2 rows in set, 1 warning (0.00 sec)

fulltext
连接是使用全文索引执行的。

ref_or_null
这个连接类型就像ref,但是加上MySQL对包含空值的行进行了额外的搜索。
这种连接类型优化通常用于解决子查询。
例如:

mysql> explain select * from graphs where templateid=1 or templateid  is null;
+----+-------------+--------+------------+-------------+---------------+----------+---------+-------+------+----------+-----------------------+
| id | select_type | table  | partitions | type        | possible_keys | key      | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+--------+------------+-------------+---------------+----------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | graphs | NULL       | ref_or_null | graphs_2      | graphs_2 | 9       | const | 2523 |   100.00 | Using index condition |
+----+-------------+--------+------------+-------------+---------------+----------+---------+-------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

index_merge
此连接类型指示使用索引合并优化。
在此情形下,输出行中的key列包含所使用的索引列表,key_len列包含用于所使用索引的最长key部分的列表。

unique_subquery
该类型在某些如下格式的IN子查询中替代eq_ref:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery只是一个索引查找函数,它完全替代了子查询以提高效率。

index_subquery
该类型与unique_subquery很相似。它也是替代IN子查询,但它适用如下格式的子查询中的非唯一索引:
value IN (SELECT key_column FROM single_table WHERE some_expr)

range
只有在给定范围内的行被检索,才使用索引来选择行。
输出行中的key列指示使用哪个索引。
key_len包含所使用的最长key部分。
此类型的ref列为NULL。
range用于当一个key列与一个常量使用=,<>,>,>=,<,<=,<=>,BETWEEN,或IN()操作符进行比较时.

mysql> explain select * from media where mediatypeid >4;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
|  1 | SIMPLE      | media | NULL       | range | media_2       | media_2 | 8       | NULL |    1 |   100.00 | Using index condition |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

index
索引连接类型与ALL相同,只是扫描索引树。有两种情况:

  • 如果索引是查询的覆盖索引,并且可以用来满足表所需的所有数据,那么只扫描索引树。此种情况下,Extra列显示Using index。一个索引扫描通常比ALL都快,因为索引的大小通常小于表数据。
  • 一个全表扫描以索引顺序读取索引来查找数据行。Extra列不显示Using index

    按索引次序扫描,先读索引,再读实际的行,结果还是全表扫描,主要优点是避免了排序。因为索引是排好的

当查询仅使用单个索引的一部分的列时,MySQL可以使用此连接类型。

mysql> explain select source from problem ;
+----+-------------+---------+------------+-------+---------------+-----------+---------+------+-------+----------+-------------+
| id | select_type | table   | partitions | type  | possible_keys | key       | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+---------+------------+-------+---------------+-----------+---------+------+-------+----------+-------------+
|  1 | SIMPLE      | problem | NULL       | index | NULL          | problem_1 | 16      | NULL | 32629 |   100.00 | Using index |
+----+-------------+---------+------------+-------+---------------+-----------+---------+------+-------+----------+-------------+
1 row in set, 1 warning (0.01 sec)

ALL
全表扫描。
通常情况下,如果表是第一个未标记为const的表,并且在所有其他情况下通常都非常糟糕,那么这通常是不好的。
通常情况下,您可以通过添加索引来避免所有的问题,这些索引可以根据前面的表中的常量值或列值来从表中进行行检索。

mysql> explain select * from problem ;       
+----+-------------+---------+------------+------+---------------+------+---------+------+-------+----------+-------+
| id | select_type | table   | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+------+-------+----------+-------+
|  1 | SIMPLE      | problem | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 32629 |   100.00 | NULL  |
+----+-------------+---------+------------+------+---------------+------+---------+------+-------+----------+-------+
1 row in set, 1 warning (0.00 sec)

possible_keys
该列指示了MySQL查找表中的行时可以选择的索引。
注意,这个列完全独立于来自EXPLAIN的输出中显示的表的顺序。
这意味着,可能在使用生成的表顺序时,一些可能的键可能无法使用。

如果该列为空,则没有相关的索引。在这种情况下,您可以通过检查WHERE子句来检查是否引用了适合于索引的某些列或列,从而提高查询的性能。如果是这样,创建一个适当的索引并再次检查查询。

key
显示MySQL在查询中实际决定使用的索引,若没有使用索引,显示为NULL

key_len
key_len列表示MySQL决定使用的键的长度(字节数)。
key_len的值使您能够确定MySQL实际使用了一个多列索引的哪些部分。
如果key列表示为NULL,key_len列也表示为NULL。
由于key的存储格式,对于一个可以为空的列,key长度比非空列更大。
key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。

ref
ref列显示哪些列或常量与键列中命名的索引相比较,以从表中选择行。
如果值是func,则使用的值是某个函数的结果。要查看是哪个函数,请在EXPLAIN后使用SHOW WARNINGS来查看EXPLAIN的扩展输出。这个函数实际上可能是一个运算符,例如算术运算符。

rows
表示MySQL认为执行该查询必须检查的行数。这是根据表统计信息及索引选用情况得出地结果。
对于InnoDB表,这个数字是一个估计值,可能并不总是准确的。

filtered
该列表示将被表条件过滤的表行的估计百分比。
即rows显示了估计的检查行数, rows*filtered/100 显示与前面的表做join的行数。
Extra
该列包含MySQL如何处理查询的附加信息。

1.Using index
该值表示相应的select操作中使用了覆盖索引(Covering Index)

覆盖索引(Covering Index)
MySQL可以利用索引返回select列表中的字段,而不必根据索引再次读取数据文件
包含所有满足查询需要的数据的索引称为覆盖索引(Covering Index)
注意:如果要使用覆盖索引,一定要注意select列表中只取出需要的列,不可select *,因为如果将所有字段一起做索引会导致索引文件过大,查询性能下降。

mysql> explain select source from problem ;
+----+-------------+---------+------------+-------+---------------+-----------+---------+------+-------+----------+-------------+
| id | select_type | table   | partitions | type  | possible_keys | key       | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+---------+------------+-------+---------------+-----------+---------+------+-------+----------+-------------+
|  1 | SIMPLE      | problem | NULL       | index | NULL          | problem_1 | 16      | NULL | 32629 |   100.00 | Using index |
+----+-------------+---------+------------+-------+---------------+-----------+---------+------+-------+----------+-------------+
1 row in set, 1 warning (0.01 sec)

2.Using where
表示mysql服务器将在存储引擎检索行后再进行过滤。许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where字句的查询都会显示”Using where”。有时”Using where”的出现就是一个暗示:查询可受益于不同的索引。

mysql> explain select * from users where name='Zabbix';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | users | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    7 |    14.29 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

3.Using temporary
表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询

这个值表示使用了内部临时(基于内存的)表。一个查询可能用到多个临时表。有很多原因都会导致MySQL在执行查询期间创建临时表。两个常见的原因是在来自不同表的上使用了DISTINCT,或者使用了不同的ORDER BY和GROUP BY列。可以强制指定一个临时表使用基于磁盘的MyISAM存储引擎。这样做的原因主要有两个:
1)内部临时表占用的空间超过min(tmp_table_size,max_heap_table_size)系统变量的限制
2)使用了TEXT/BLOB 列

mysql> explain select * from trends_uint where itemid in (select itemid from trends order by clock) order by itemid;
+----+-------------+-------------+------------+-------+---------------+---------+---------+----------------------+----------+----------+---------------------------------------------------------+
| id | select_type | table       | partitions | type  | possible_keys | key     | key_len | ref                  | rows     | filtered | Extra                                                   |
+----+-------------+-------------+------------+-------+---------------+---------+---------+----------------------+----------+----------+---------------------------------------------------------+
|  1 | SIMPLE      | trends      | NULL       | index | PRIMARY       | PRIMARY | 12      | NULL                 | 18369191 |     0.38 | Using index; Using temporary; Using filesort; LooseScan |
|  1 | SIMPLE      | trends_uint | NULL       | ref   | PRIMARY       | PRIMARY | 8       | zabbix.trends.itemid |      270 |   100.00 | NULL                                                    |
+----+-------------+-------------+------------+-------+---------------+---------+---------+----------------------+----------+----------+---------------------------------------------------------+
2 rows in set, 1 warning (0.00 sec)

4.Using filesort
MySQL中无法利用索引完成的排序操作称为“文件排序”

mysql> explain select * from trends_uint order by num;
+----+-------------+-------------+------------+------+---------------+------+---------+------+----------+----------+----------------+
| id | select_type | table       | partitions | type | possible_keys | key  | key_len | ref  | rows     | filtered | Extra          |
+----+-------------+-------------+------------+------+---------------+------+---------+------+----------+----------+----------------+
|  1 | SIMPLE      | trends_uint | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 30427219 |   100.00 | Using filesort |
+----+-------------+-------------+------------+------+---------------+------+---------+------+----------+----------+----------------+
1 row in set, 1 warning (0.01 sec)

5.Using join buffer
该值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进能。

mysql> explain select * from (select * from media_type) a ,media b where a.mediatypeid=b.mediatypeid;
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                              |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
|  1 | SIMPLE      | media_type | NULL       | ALL  | PRIMARY       | NULL | NULL    | NULL |    4 |   100.00 | NULL                                               |
|  1 | SIMPLE      | b          | NULL       | ALL  | media_2       | NULL | NULL    | NULL |    5 |   100.00 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
2 rows in set, 1 warning (0.00 sec)

6.Impossible where
这个值强调了where语句会导致没有符合条件的行。


mysql> explain select * from trends_uint where 1=2;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra            |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
|  1 | SIMPLE      | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | Impossible WHERE |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
1 row in set, 1 warning (0.00 sec)

7.Select tables optimized away
这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行.

8.Index merges
当MySQL 决定要在一个给定的表上使用超过一个索引的时候,就会出现以下格式中的一个,详细说明使用的索引以及合并的类型。
Using sort_union(…)
Using union(…)
Using intersect(…)


参考:https://www.cnblogs.com/gomysql/p/3720123.html
参考:https://www.cnblogs.com/xiaoboluo768/p/5400990.html
参考:https://blog.csdn.net/b1303110335/article/details/51174540

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值