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详细说明的主要内容,如果未能解决你的问题,请参考以下文章