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

本文深入解析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 RESULTMySQL 选择使用临时表来完成 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全表扫描

一般执行效率从高到低为:
const > eq_ref > 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 的内存块来加快查询速度,也就是我们所讲的 基于块的嵌套循环算法
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值