MySQL - Explain详解

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: MySQL - Explain详解

1. 前言

Server version: 5.7.36 MySQL Community Server (GPL)

mysql官方文档:https://dev.mysql.com/doc/refman/5.7/en/explain-output.html

explain(执行计划),使用 explain 关键字可以模拟优化器执行 sql 查询语句,从而知道 MySQL 是如何处理 sql 语句。explain 主要用于分析查询语句或表结构的性能瓶颈。

explain select * from user where phone = '15233658888';

explain 输出内容大致如下:

2. explain的作用

通过 explain + sql 语句可以知道如下内容:

  1. 表的读取顺序(对应id)
  2. 数据读取操作的操作类型(对应select_type)
  3. 哪些索引可以使用(对应possible_keys)
  4. 哪些索引被实际使用(对应key)
  5. 表直接的引用(对应ref)
  6. 每张表有多少行被优化器查询(对应rows)

3. explain的内容

3.1 id

select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序,该字段通常与table字段搭配来分析。

  1. id 相同时,执行顺序由上至下
  2. 如果是子查询,id 的序号会递增,id 值越大优先级越高,越先被执行
  3. id 如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id 值越大,优先级越高,越先执行

3.2 select_type

查询的类型,主要用于区别普通查询、联合查询、子查询等复杂的查询。其值主要有六个:

  1. SIMPLE

简单的 select 查询,查询中不包含子查询或 union 查询。

  1. PRIMARY

查询中若包含任何复杂的子部分,最外层查询为 PRIMARY,也就是最后加载的就是 PRIMARY。

  1. UNION

此查询是 UNION 中的第二个或后面的SELECT语句

若第二个 select 出现在 union 后,则被标记为 UNION,若 union 包含在 from 子句的子查询中,外层 select 将被标记为 DERIVED。

  1. DEPENDENT UNION

UNION 中的第二个或后面的SELECT语句,取决于外面的查询。

  1. UNION RESULT

UNION的结果。

  1. SUBQUERY

子查询中的第一个SELECT,结果不依赖于外部查询

在 select 或 where 列表中包含了子查询,就为被标记为 SUBQUERY。

  1. DERIVED

在 from 列表中包含的子查询会被标记为 DERIVED,MySQL 会递归执行这些子查询,将结果放在临时表中。

3.3 table

显示这一步所访问数据库中表名称(显示这一行的数据是关于哪张表的),有时不是真实的表名字,可能是简称,例如tab_a,tab_a,也可能是第几步执行的结果的简称

3.4 partitions

官方定义为The matching partitions(匹配的分区),对于非分区表值为null。

3.5 type

表示查询所使用的访问类型,type 的值主要有八种,该值表示查询的 sql 语句好坏,从最好到最差依次为:

NULL > system > const > eq_ref > ref > range > index > ALL

  1. NULL

MySQL 在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。

  1. system

system 是 const 的特例,表里只有一条元组匹配时为 system。

  1. const

MySQL 能对查询的某部分进行优化并将其转化成一个常量(可以看show warnings 的结果)。用于 primary key 或 unique key 的所有列与常数比较时,表最多有一个匹配行,读取1次,速度比较快。

  1. eq_ref

唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描;

primary key 或 unique key 索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录。这可能是在 const 之外最好的联接类型了,简单的 select 查询不会出现这种 type。

  1. ref

使用非唯一索引或非唯一索引前缀进行的查找;

相比 eq_ref,不使用唯一索引,而是使用普通索引或者唯一性索引的部分前缀,索引要和某个值相比较,可能会找到多个符合条件的行。

  1. range

按指定范围(如in()、between and、>、<、>=等,但是前提是此字段要建立索引)来检索,很常见。

如:select * from student where id < 5,id上要有索引。

  1. index

全"表"扫描,但是是在索引树中扫描,通常比 ALL 快,因为索引文件通常比数据文件小,index 扫描是通过二叉树的方式扫描,而 ALL 是扫描物理表。也就是说虽然 ALL 和 index 都是读全表,但 index 是从索引中读取的,而 ALL 是从硬盘中读的。

例如:select name from student,但 name 字段上需要建立索引,也就是查询的字段属于索引中的字段。

  1. ALL

全表扫描,扫描完整的物理表,此时就需要优化了。

3.6 possible_keys

指出 MySQL 能在该表中可能使用的索引,显示的是索引的名称,多个索引用逗号隔开。

explain 时可能出现 possible_keys 有列,而 key 显示 NULL 的情况,这种情况是因为表中数据不多,mysql认为索引对此查询帮助不大,选择了全表查询。

如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查 where 子句看是否可以创造一个适当的索引来提高查询性能,然后用 explain 查看效果。

3.7 key

MySQL决定实际用到的索引,显示的是索引的名称,多个索引用逗号隔开。

如果没有使用索引,则该列是 NULL。如果想强制 MySQL 使用或忽视 possible_keys 列中的索引,在查询中使用 force index、ignore index。

3.8 key_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的)。

不损失精确性的情况下,长度越短越好。

key_len只计算where条件用到的索引长度,而排序和分组就算用到了索引,也不会计算到key_len中。

举例来说,film_actor 的联合索引 idx_film_actor_id 由 film_id 和 actor_id 两个 int 列组成,并且每个 int 是4字节。通过结果中的 key_len = 4 可推断出查询使用了第一个列:film_id 列来执行索引查找。

计算key_len的公式:

varchr(10)变长字段且允许NULL = 10 * ( character set:utf8=3, gbk=2, latin1=1) + 1(NULL) + 2(变长字段)

varchr(10)变长字段且不允许NULL = 10 *( character set:utf8=3, gbk=2, latin1=1) + 2(变长字段)

char(10)固定字段且允许NULL = 10 * ( character set:utf8=3, gbk=2, latin1=1)+1(NULL)

char(10)固定字段且不允许NULL = 10 * ( character set:utf8=3, gbk=2, latin1=1)

3.9 ref

列与索引的比较,表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值,常见的有:const(常量),字段名(例:film.id)

3.10 rows

显示 MySQL 认为执行查询时必须要返回的行数,可结合 type 和 key 分析,没有用上索引的情况下,会全表扫描。rows 的值越小越好,说明检索的数据少,注意这个不是结果集里的行数。

3.11 filtered

给出了一个百分比的值,这个百分比值和 rows 列的值一起使用,可以估计出那些将要和执行计划中的前一个表(前一个表就是指 id 列的值比当前表的 id 小的表)进行连接的行的数目。

3.12 Extra

此字段显示一些额外的信息,但是此字段的部分值具有优化的参考意义:

  1. using where

查询的列未被索引覆盖,where 筛选条件非索引的前导列。

  1. using index:

表示使用了覆盖索引。这个值重点强调了只需要使用索引就可以满足查询表的要求,不需要直接访问表数据。

查询的列被索引覆盖,并且 where 筛选条件是索引的前导列, 是性能高的表现。一般是使用了覆盖索引(索引包含了所有查询的字段)。对于innodb来说,如果是辅助索引性能 会有不少提高。

  1. Using index condition:

查询的列不完全被索引覆盖,where条件中是一个查询的范围。

  1. NULL

查询的列未被索引覆盖,并且 where 筛选条件是索引的前导列,意味着用到了索引,但是部分字段未被索引覆盖,必须通过"回表"来实现,不是纯粹地用到了索引,也不是完全没用到索引。

  1. using join buffer

这个值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进性能

  1. using filesort

这是 order by 语句的结果。这可能是一个CPU密集型的过程。using filesort 表示出现了文件内排序,MySQL 会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。此时 MySQL 会根据联接类型浏览所有符合条件的记录,并保存排序关键字和行指针,然后排序关键字并按顺序检索行信息。表示很不好的现象,必须要优化,特别是大表,可以通过选择合适的索引来改进性能,用索引来为查询结果排序。

  1. using temporary:

MySQL 需要创建一张临时表来保存中间结果。 也就是说,需要先把数据放到临时表中,然后从临时表中获取需要的数据。出现这种临时表,也是必须需要优化的地方,特别是数据量大的情况。两个常见的原因是在来自不同表的列上使用了 distinct,或者使用了不同的 order by 和 group by 列。

首先是想到用索引来优化。

4. 总结

  1. EXPLAIN 不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况;
  2. EXPLAIN 不考虑各种 Cache;
  3. EXPLAIN 不能显示 MySQL 在执行查询时所作的优化工作;
  4. 部分统计信息是估算的,并非精确值;
  5. EXPALIN 只能解释 SELECT 操作,其他操作要重写为 SELECT 后查看执行计划。
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
SQL 存储 关系型数据库
SQL优化之Explain详解(mysql)
`Explain`是MySQL中用于分析SQL查询执行计划的工具。它可以帮助我们了解MySQL如何执行SQL语句,包括如何使用索引、预计的行数以及查询的顺序。以下是`Explain`输出的关键列及其含义的简要摘要: 1. **id**:查询的序列号,表示查询中的子句层次,id越大优先级越高。 2. **select_type**:表示查询的类型,如SIMPLE(简单查询)、PRIMARY(主查询,多表查询中的第一个查询)、SUBQUERY(子查询)、DERIVED(派生表)或UNION(UNION操作的查询部分)。 3. **table**:查询涉及的表名,如果是子查询,可能显示为衍生表
33 0
|
2天前
|
存储 SQL 关系型数据库
MySQL 底层数据结构 聚簇索引以及二级索引 Explain的使用
MySQL 底层数据结构 聚簇索引以及二级索引 Explain的使用
14 0
|
2月前
|
SQL 缓存 关系型数据库
MySQL的万字总结(缓存,索引,Explain,事务,redo日志等)
MySQL的万字总结(缓存,索引,Explain,事务,redo日志等)
69 0
|
7月前
|
SQL 存储 关系型数据库
【MYSQL高级】Mysql的SQL性能分析【借助EXPLAIN分析】
【MYSQL高级】Mysql的SQL性能分析【借助EXPLAIN分析】
73 0
|
3月前
|
存储 关系型数据库 MySQL
MySQL技能完整学习列表6、查询优化——1、EXPLAIN命令的使用——2、索引优化
MySQL技能完整学习列表6、查询优化——1、EXPLAIN命令的使用——2、索引优化
23 0
|
4月前
|
SQL 关系型数据库 MySQL
MySQL SQL性能分析 慢查询日志、explain使用
MySQL SQL性能分析 慢查询日志、explain使用
119 0
|
4月前
|
SQL 机器学习/深度学习 关系型数据库
MySQL - Explain深度剖析
MySQL - Explain深度剖析
43 0
|
5月前
|
SQL 关系型数据库 MySQL
mysql explain 详解及sql优化指南
mysql explain 详解及sql优化指南
31 0
|
5月前
|
SQL 存储 关系型数据库
【MySQL】MySQL Explain性能调优详解
【MySQL】MySQL Explain性能调优详解
63 0
【MySQL】MySQL Explain性能调优详解
|
5月前
|
SQL 存储 关系型数据库
谈谈MYSQL中的Explain
谈谈MYSQL中的Explain