MySql查询优化-执行计划explain详细说明

Posted Leo Han

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySql查询优化-执行计划explain详细说明相关的知识,希望对你有一定的参考价值。

我们在mysql中一般相对查询进行优化的时候,都会借助MySql提供的查询计划explain进行分析,一般我们在我们需要执行查询的SQL前加上explain关键字,然后在此基础上进行分析,一般常见的explain输出如下:

对上面这几个属性,我们一个一个俩分析说明。

id

在一个大的查询包含多个子查询中,每个子查询的执行顺序,id相同,从上往下执行;id不同,id值越大优先级越高,越先被执行;id为nul时表示一个结果集,不需要使用它查询,一般出现在包含union等查询中

mysql> explain select * from etl_process_log where id in(select id from etl_process_log where data_start_hour=2020010100);
+----+-------------+-----------------+------------+--------+---------------+---------+---------+-----------------------------+------+----------+-------------+
| id | select_type | table           | partitions | type   | possible_keys | key     | key_len | ref                         | rows | filtered | Extra       |
+----+-------------+-----------------+------------+--------+---------------+---------+---------+-----------------------------+------+----------+-------------+
|  1 | SIMPLE      | etl_process_log | NULL       | ALL    | PRIMARY       | NULL    | NULL    | NULL                        | 4521 |    10.00 | Using where |
|  1 | SIMPLE      | etl_process_log | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | etl_test.etl_process_log.id |    1 |   100.00 | NULL        |
+----+-------------+-----------------+------------+--------+---------------+---------+---------+-----------------------------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)


mysql> explain select id from etl_process_log where data_start_hour=2020010100 union select id from etl_process_log where id=4;
+----+--------------+-----------------+------------+-------+---------------+---------+---------+-------+------+----------+-----------------+
| id | select_type  | table           | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra           |
+----+--------------+-----------------+------------+-------+---------------+---------+---------+-------+------+----------+-----------------+
|  1 | PRIMARY      | etl_process_log | NULL       | ALL   | NULL          | NULL    | NULL    | NULL  | 4521 |    10.00 | Using where     |
|  2 | UNION        | etl_process_log | NULL       | const | PRIMARY       | PRIMARY | 4       | 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)

如上面id=null的则是为了union结果进行去重的时候,临时中间结果,而union all则不需要:


mysql> explain select id from etl_process_log where data_start_hour=2020010100 union all select id from etl_process_log where id=4;
+----+-------------+-----------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table           | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-----------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
|  1 | PRIMARY     | etl_process_log | NULL       | ALL   | NULL          | NULL    | NULL    | NULL  | 4521 |    10.00 | Using where |
|  2 | UNION       | etl_process_log | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | Using index |
+----+-------------+-----------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

select_type

select_type表名的是每个子查询的查询类型,常见的类型有如下几种:

select_type说明
SIMPLE不包含任何子查询或union等查询
PRIMARY包含子查询的最外层查询
SUBQUERY如果包含子查询的查询语句不能够转为对应的 semi-join 的形式,并且该子查询是不相关子查询,并且查询

优化器决定采用将该子查询物化的方案来执行该子查询时,该子查询的第一个 SELECT 关键字代表的那个查
询的 select_type 就是 SUBQUERY |
|DERIVED|对于采用物化的方式执行的包含派生表的查询,该派生表对应的子查询的 select_type 就是 DERIVED|
|MATERIALIZED|当查询优化器在执行包含子查询的语句时,选择将子查询物化之后与外层查询进行连接查询时,该子查询对
应的 select_type 属性就是 MATERIALIZED|
|UNION|对于包含 UNION 或者 UNION ALL 的大查询来说,它是由几个小查询组成的,其中除了最左边的那个小查询以
外,其余的小查询的 select_type 值就是 UNION |
|UNION RESULT|MySQL 选择使用临时表来完成 UNION 查询的去重工作,针对该临时表的查询的 select_type 就是 UNION
RESULT |

type

type表名MySQL访问一个表的访问方法,非常重要,可以看到有没有走索引,主要有如下几种

type说明
system当表中只有一条记录并且该表使用的存储引擎的统计数据是精确的,比如MyISAM、Memory,那么对该表的访问方法就是 system
const当我们根据主键或者唯一二级索引列与常数进行等值匹配时,对单表的访问方法
eq_ref在连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的方式进行访问的(如果该主键或者唯一二级索引是联合索引的话,所有的索引列都必须进行等值比较)
ref通过普通的二级索引列与常量进行等值匹配时来查询某个表
fulltext全文索引
ref_or_null当对普通二级索引进行等值匹配查询,该索引列的值也可以是 NULL 值时
unique_subquery在子查询中使用了eq_ref
range通过索引进行范围查找
index遍历索引
ALL全表扫描

possible_keys

possible_keys 可能使用的索引,注意不一定会使用。查询涉及到的字段上若存在索引,则该索引将被
列出来。当该列为 NULL时就要考虑当前的SQL是否需要优化了

key

key 显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL,查询中若使用了覆盖索引(覆盖索引:索引的数据覆盖了需要查询的所有数据),则该索引仅出现在
key列表中

key_length

key_length 索引长度

ref

当使用索引列等值匹配的条件去执行查询时,也就是在访问方法是 const 、 eq_ref 、 ref 、 ref_or_null 、unique_subquery 、 index_subquery 其中之一时, ref 列展示的就是与索引列作等值匹配的是什么类型

rows

执行计划的 rows 列就代表预计需要扫描的行数,如果使用索引来执行查询时,执行计划的 rows 列就代表预计扫描的索引记录行数。

Extra

提供一些额外信息说明,常见的有:

Extra信息说明
Using index使用覆盖索引
Using where使用where条件过滤
Using filesort使用文件排序,使用非索引列进行排序时出现,非常消耗性能,尽量优化
Using temporary使用了临时表
Using join buffer (Block Nested Loop)在连接查询执行过程中,当被驱动表不能有效的利用索引加快访问速度, MySQL 一般会为其分配一块名叫join buffer 的内存块来加快查询速度,也就是我们所讲的 基于块的嵌套循环算法

以上是关于MySql查询优化-执行计划explain详细说明的主要内容,如果未能解决你的问题,请参考以下文章

MySQL优化从执行计划开始(explain超详细)

Mysql(21)—EXPLAIN执行计划的字段详解

MySQL EXPLAIN 命令: 查看查询执行计划

Explain 执行计划 和 SQL优化

如何根据Explain执行计划对数据库查询语句进行优化

如何根据Explain执行计划对数据库查询语句进行优化