Mysql- Explain

Explain含义

Explain是SQL分析工具中非常重要的一个功能,它可以模拟优化器执行查询语句,帮助我们理解查询是如何执行的;分析查询执行计划可以帮助我们发现查询瓶颈,优化查询性能。

Explain作用

  • 表的读取顺序
  • SQL执行时查询操作类型
  • 可以使用那些索引
  • 世纪使用那些索引
  • 每张表有多少行记录被扫描
  • SQL语句性能分析

Explain用法

Mysql5.7版本之前,使用Explain Extended在Explain的基础上额外多返回filtered列与extra

Explain Extended select * from users;

Mysql5.7版本之前,使用Explain Partitions在Explain的基础上额外多返回partitions列

Explain Partitions select * from users;

Mysql5.7版本引入了这两个特性,直接使用Explain关键字可以讲partitions、filtered、extra列直接查询出来

Explain语句返回列的各列含义

列名 含义
id 每个select都有一个对一个的ID,并且是从1开始自增的
select_type 查询语句执行的查询操作类型
table 表名
partitions 表分区情况
type 查询所用到的访问类型
possible_keys 可能用到的索引
key 实际查询用到的索引
key_len 所使用到的索引长度
ref 使用到索引时,与索引进行等值匹配到列或者常量
rows 预计扫描的行数(索引行数或者表记录行数)
filtered 表示符合查询条件的数据百分比
Extra SQL执行的额外信息

Explain返回列详解

id

每个select都有一个对应的id,并且是从1开始自增的

  • 如果id序号相同,从上往下执行
  • 如果id序号不同,序号大的先执行
  • 如果两种都存在,先执行序号大,在同级从上往下执行。
  • 如果是NULL,最后执行。表示结果集,并且不需要使用它来进行查询。

Select_type

simple:简单select,不包括union与子查询

primary:复杂查询中最外层查询,比如使用union或union all时,id为1的记录的select_type通常是primary

explain
select id from users
union
select id from products;

image-20230528205108988

Subquery: 指在select语句中出现的字查询语句,结果不依赖于外部查询(不在from语句中)

explain
select orders.*, (select name from products where id = 1) from orders;

image-20230528205440711

dependent subquery: 指在select语句中出现的查询语句,结果依赖于外部查询

explain
select orders.* (select name from products where products.id = orders.user_id) from orders;

derived: 派生表,在from子句的查询语句,表示从外部数据源中推导出来的,而不是从select语句中的其他列中选择出来的。

set session optimizer_switch='derived_merge=off'; # 关闭mysql5.7对衍生表合并优化

explain
select * from (select user_id from orders where id = 1) as temp;

set session optimizer_switch='derived_merge=on'; # 关闭mysql5.7对衍生表合并优化

union: 分union与union all两种,若第二个select 出现在union之后,则被标记为union;如果union被from子句的字查询包含,那么第一个select会被标记为derived;union会针对相对的结果进行去重,union all不会进行去重处理。

explain
select * from (
select id from products where price = 10
  union
select id from orders where user_id in(1,3)
  union
select id from users where name = 'zx'
) as temp;

dependent union: 当union作为字查询时,其中第一个union为dependent subquery, 第二个union为dependent union。

explain
select * from orders where id in(
select id from products where price = 10
  union
select id from orders where user_id= 2
  union
select id from users where name = 'zx'
);

image-20230528211210560

union result: 如果两个查询中有相同的列值,则会对这些值进行去重

explain
select id from users
union
select id from products;

image-20230528211521630

type

查询所使用到到访问类型,效率从高到低为:system->const-> eq ref -> ref -> fulltext -> ref or null -> range -> index -> All, 一般来说保证range级别,最好能达到ref级别

system

const类型的一种特殊场景,查询的表中只有一行记录的情况,并且该表使用的存储引擎的统计数据是精确的,innodb存储引擎的统计数据不是精确的,虽然只有一条数据但是type类型为all;

image-20230528212232663

Memory存储引擎的统计数据是精确的,所以当只有一条记录的时候type类型为system

image-20230528212504900

const

基于主键或唯一索引查看一行,当mysql对查询某部分进行优化,并转换为一个常量时,使用这些类型访问转换成常量查询,效率高

image-20230528212741168

eq_ref

基于主键或唯一索引连接两个表,对于每个索引键值,只有一条匹配记录,被驱动表的类型为eq_ref

image-20230528213055672

ref

基于非唯一索引连接两个表或通过二级索引列与常量进行等值匹配,可能会存在多条匹配记录

  • 关联查询,使用非唯一索引进行匹配

image-20230528213305725

  • 简单查询,使用二级索引列匹配

image-20230528213407885

range

使用非唯一索引扫描部分索引,比如使用索引获取某些范围区间的记录

image-20230528213741394

index

扫描整个索引就能拿到结果,一般是二级索引,这种查询一般为使用覆盖索引

explain
select user_id from orders;

image-20230528214030241

all

扫描整个表进行匹配,即扫描聚簇索引树

Null

mysql优化过程中分解语句就已经可以获取到结果,执行时甚至不用访问表或索引

explain
select min(id) from users;

image-20230528214335806


文章作者: Tariq
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Tariq !
  目录