Explain关键字 什么是MySQL的执行计划?

本文作者王良辰 , 京东中台架构师 , 擅长分布式系统及高可用、高并发系统架构与设计 。曾经为企业开发过多个通用脚手架 , 推崇以技术手段提升开发效率、约束开发行为 。
什么是Explain 
Explain被称为执行计划 , 在语句之前增加 explain 关键字 , MySQL 会在查询上设置一个标记 , 模拟MySQL优化器来执行SQL语句 , 执行查询时 , 会返回执行计划的信息 , 并不执行这条SQL 。(注意 , 如果 from 中包含子查询 , 仍会执行该子查询 , 将结果放入临时表中) 。
 
Explain可以用来分析SQL语句和表结构的性能瓶颈 。通过explain的结果 , 可以了解到如数据表的查询顺序、数据查询操作的操作类型、哪些索引可以被命中、哪些索引实际会命中、每个数据表有多少行记录被查询等信息 。
 
Explain命令扩展explain extended 
在explain的基础上提供一些额外的查询信息 , 在explian extended执行以后 , 通过show warnings命令可以得到优化后的查询语句 , 可以看出优化器做了哪些工作 , 还可以通过某些数据估算表连接的行数 。
explain partitions 
用于分析使用了分区的表 , 会显示出可能用到的分区 。
 
两点重要提示1. Explain结果是基于数据表中现有数据的 。2. Explain结果与MySQL版本有很大的关系 , 不同版本的优化器的优化策略不同 。 
本文示例使用的数据库表 

Explain关键字 什么是MySQL的执行计划?

文章插图
 
Explain命令(关键字) 
explain简单示例mysql>explain select * from t_user;
Explain关键字 什么是MySQL的执行计划?

文章插图
 
在查询中的每个”表”会输出一行 , 这里的“表”的意义非常广泛 , 不仅仅是数据库表 , 还可以是子查询、一个union 结果等 。
explain结果列说明【id列】 
id列是一个有顺序的编号 , 是查询的顺序号 , 有几个 select 就显示几行 。id的顺序是按 select 出现的顺序增长的 。id列的值越大执行优先级越高越先执行 , id列的值相同则从上往下执行 , id列的值为NULL最后执行 。
【select_type列】 
select_type列的值标明查询的类型:
 
1)simple:表明当前行对应的select是简单查询 , 不包含子查询和union
 
2)primary:表明当前行对应的select是复杂查询中最外层的 select
 
3)subquery:表明当前行对应的select是包含在 select 中的子查询(不在 from 子句中)
 
4)derived:表明当前行对应的select是包含在 from 子句中的子查询 。
 
MySQL会创建一个临时表来存放子查询的查询结果 。用如下的语句示例说明:
 
explain select (select 1 fromt_user where user_id=1) from (select * from t_group where group_id=1) tmp;
Explain关键字 什么是MySQL的执行计划?

文章插图
 
*注意 , 在资料收集过程中 , 发现不同版本的MySQL表现不一致 , 经反复对比 , 5.7及以后版本的输出如下:
Explain关键字 什么是MySQL的执行计划?

文章插图
 
很显然 , MySQL在这方面进行了优化.
 
*注意 , MySQL不同版本Explain表现差异很大 , 有些场景 , 从语句层面看 , 是要使用到索引 , 但经过优化器分析 , 结合表中现有数据 , 如果MySQL认为全表扫描性能更优 , 则会使用全表扫描 。
 
5)union:表明当前行对应的select是在 union 中的第二个和随后的 select
 
6)union result:表明当前行对应的select是从 union 临时表检索结果的 select
 
explain select 1 union all select 2 fromdual;
Explain关键字 什么是MySQL的执行计划?

文章插图
 
MySQL5.7及以后同样做了优化
Explain关键字 什么是MySQL的执行计划?

文章插图
 
【table列】 
table列的结果表明当前行对应的select正在访问哪个表 。当查询的<from>子句中有子查询时 , table列是 <derivedN> 格式 , 表示当前的select依赖 id=N结果行对应的查询 , 要先执行 id序号=N 的查询 。当存在 union 时 , UNION RESULT 的 table 列的值为<unionN1,N2> , N1和N2表示参与 union 的select 行的id序号 。


推荐阅读