SQL优化之Explain详解(mysql)

本文涉及的产品
可观测监控 Prometheus 版,每月50GB免费额度
云原生网关 MSE Higress,422元/月
应用实时监控服务-应用监控,每月50GB免费额度
简介: `Explain`是MySQL中用于分析SQL查询执行计划的工具。它可以帮助我们了解MySQL如何执行SQL语句,包括如何使用索引、预计的行数以及查询的顺序。以下是`Explain`输出的关键列及其含义的简要摘要:1. **id**:查询的序列号,表示查询中的子句层次,id越大优先级越高。2. **select_type**:表示查询的类型,如SIMPLE(简单查询)、PRIMARY(主查询,多表查询中的第一个查询)、SUBQUERY(子查询)、DERIVED(派生表)或UNION(UNION操作的查询部分)。3. **table**:查询涉及的表名,如果是子查询,可能显示为衍生表

 

抛问题:

1. Explain是什么?



一、Explain

1.1 explain作用

       在sql语句前添加explain,作用是查看mysql对这条sql的执行计划信息。

       思考:MYSQL执行SQL语句时一定按这个执行计划执行么?

1.2 explain列说明

在一条简单SQL前面添加explain查看有哪些列,如下:

1711791995457.png

       每个select对应一个id值,其值是按 select 出现的顺序增长的。

       注:id值越大执行优先级越高,id相同则从上往下执行,id为NULL最后执行


select_type

       每个select对应一个select_type,表示select的复杂度,有:

       SIMPLE:简单查询。查询不包含子查询和union,如上图

       PRIMARY:对于包含UNION、UNION ALL或者子查询的大查询来说,它是由几个小查询组成的,其中最左边的那个查询的select_type值就是PRIMARY

       SUBQUERY:包含在 select 中的子查询(不在 from 子句中)

       DERIVED:对于包含‘派生表’的查询

       UNION:在 union 中的第二个和随后的 select


table

       这一列表示 explain 的一行正在访问哪个表。

       当 from 子句中有子查询时,table列是 <derivenN> 格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查 询。

       当有 union 时,UNION RESULT 的 table 列的值为<union1,2>,1和2表示参与 union 的 select 行id。


partiitons

       匹配的分区信息


type

       这一列表示关联类型或访问类型

       效率从最优到最差分别为:system > const > eq_ref > ref > range > index > ALL

       SQL性能优化的目标:至少要达到range级别,要求是ref级别,最好是consts级别。

       system当表中只有一条记录并且该表使用的存储引擎的统计数据都是精确地,表最多有一个匹配行,读取1次,速度比较快。

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

       eq_ref:primary key 或 unique key 索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录。

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

       range:用索引获取某些范围区间的记录。


select_type

       每个select对应一个select_type,表示select的复杂度

       SIMPLE:简单查询。查询不包含子查询和union,如上图

       PRIMARY:对于包含UNION、UNION ALL或者子查询的大查询来说,它是由几个小查询组成的,其中最左边的那个查询的select_type值就是PRIMARY

       SUBQUERY:包含在 select 中的子查询(不在 from 子句中)

       DERIVED:对于包含‘派生表’的查询

       UNION:在 union 中的第二个和随后的 select


possible_keys

       标识某个表查询时可能使用哪些索引来查找。        


key

       实际使用哪个索引。

       当possible_keys有值,而key没有值时,可能是因为表数据很少,mysql认为没有必要走索引,直接全表查询了。
   当possible_keys为null时,可根据实际情况在where条件中添加索引来提升查询效率。


key_len(key_len值计算)

        实际使用到的索引的字节数,帮我们检查是否充分利用上了索引,对于联合索引有一定的参考意义。

比如有列n和address的联合索引(表my_datas字段有id, n, address 和 time)

image.png

key_len=5,通过计算索引占的字节数来判断出查询使用了联合索引中的第一个列。

key_len的计算:(举几个类型)

       测试表test1

image.png

字符串:char(n)和varchar(n),5.0.3以后版本中,n均代表字符数,而不是字节数,如果是utf-8,一个数字或字母占1个字节,一个汉字占3个字节

  • char(n):如果存汉字长度就是 4n 字节(若可为空 则+1)
    image.png
    col1_char是char(4),那么len应该是 4*4 + 可为空1 = 17
    explain中key_len值为17
  • varchar(n):如果存汉字则长度是 4n + 2 字节(若可为空 则+1),加的2字节用来存储字符串长度,因为 varchar是变长字符串。
    image.png
          col2_varchar是varchar(32),那么len应该是 32 * 4 + 2 + 1 = 131
    explain中key_len值为131

数值类型

  • tinyint:1字节(若可为空 则+1)
    image.gif image.png
    col3_tinyint是tinyint,那么len应该是 1+可为空1 = 2
    explain中key_len值为2
  • smallint:2字节(若可为空 则+1)
    image.gif image.png
    col4_smallint是smallint,那么len应该是 2+可为空1 = 3
    explain中key_len值为3
  • int:4字节(若可为空 则+1)
    image.gif image.png
    col5_int是int,那么len应该是 4+可为空1 = 5
    explain中key_len值为5
  • bigint:8字节 (若可为空 则+1)
    image.gif image.png
    col6_bigint是bigint,那么len应该是 8+可为空1 = 9
    explain中key_len值为9

时间类型

  • date:3字节(若可为空 则+1)
    image.gif image.png
    col7_date是date,那么len应该是 3 + 可为空1 = 4
    explain中key_len值为4
  • timestamp:4字节(若可为空 则+1)
    image.gif image.png
    col8_timestamp是timestamp,那么len应该是 4+可为空1 = 5
    explain中key_len值为5
  • datetime:无小数秒位数,占5个字节。datetime(n) 其中n是保留的小数秒位数,额外占的存储空间分别为
    n=0时      额外空间0字节
    n=1(或2)  额外空间1字节
    n=3(或4)  额外空间2字节
    n=5(或6)  额外空间3字节
    image.gif image.png
    col9_datetime是datetime,那么len应该是 5+可为空1 = 6
    explain中key_len值为6

注:

  •    myisam 表,单列索引,最大长度不能超过 1000 bytes,否则会报警,但是创建成功,最终创建的是前缀索引(取前333个字符);
  •    myisam 表,组合索引,索引长度和不能超过 1000 bytes,否则会报错,创建失败;
  •    innodb 表,单列索引,超过 767 bytes的,给出warning,最终索引创建成功,取前缀索引(取前 255 字符);
  •    innodb表,组合索引,各列长度不超过 767 bytes ,如果有超过 767 bytes 的,则给出报警,索引最后创建成功, 但是对于超过 767 字节的列取前缀索引,与索引列顺序无关,总和不得超过 3072 ,否则失败,无法创建;

ref

       这一列显示了在key列记录的索引中,表查找值所用到的列或常量,常见的有:const(常量)、字段名(库名.表名.列名 如test.test.col1_char)

image.gif image.png


rows

       这一列是mysql估计要读取并检测的行数,值越小越优

       注意这个不是结果集里的行数                


filtered

       通过索引扫描表估计要读取并检测的行数rows。

       使用额外的查询条件对rows行的数据进行过滤行得有行数n占rows的比例,

       即 n/rows * 100%


Extra

       sql执行计划比较重要的参考信息,常见重要信息如下:

  • 1 Using index:使用索引覆盖
    索引覆盖:查询的字段信息从这条sql使用的索引(辅助索引)树中获取。如:
    image.gif image.png
    查询的字段是索引(col4_smallint)中的字段col4_smallint信息
    也就是说,不需要通过辅助索引找到主键,再通过主键树获取想要的信息
  • 2 Using where:使用where查询数据,需要回表去获取需要的数据
    image.gif image.png
  • 3 Using index condition:相当于索引覆盖后通过主键回表查询,再通过where过滤
    image.gif image.png
  • 4 Using temporary:创建一张临时表来处理查询
    image.gif image.png
  • Using filesort:顾名思义,使用文件(磁盘中)排序。mysql做了优化,数据较少时排序是在内在中进行的,数据量较大时才会在磁盘中进行排序。出现这种情况,就要考虑添加索引来优化SQL了。
    image.gif image.png
    col1_char未创建索引,mysql先预览整个表对col1_char进行排序和对应的主键值序列,再通过主键值回主键索引树查询数据返回。
    对col1_char添加索引之后,执行计划结果如下:
    image.gif image.png
  • Select tables optimized away:使用函数来查询某个索引信息时
    image.gif image.png
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
17天前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
118 9
|
10天前
|
SQL 存储 关系型数据库
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
本文详细介绍了MySQL中的SQL语法,包括数据定义(DDL)、数据操作(DML)、数据查询(DQL)和数据控制(DCL)四个主要部分。内容涵盖了创建、修改和删除数据库、表以及表字段的操作,以及通过图形化工具DataGrip进行数据库管理和查询。此外,还讲解了数据的增、删、改、查操作,以及查询语句的条件、聚合函数、分组、排序和分页等知识点。
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
|
15天前
|
SQL Oracle 数据库
使用访问指导(SQL Access Advisor)优化数据库业务负载
本文介绍了Oracle的SQL访问指导(SQL Access Advisor)的应用场景及其使用方法。访问指导通过分析给定的工作负载,提供索引、物化视图和分区等方面的优化建议,帮助DBA提升数据库性能。具体步骤包括创建访问指导任务、创建工作负载、连接工作负载至访问指导、设置任务参数、运行访问指导、查看和应用优化建议。访问指导不仅针对单条SQL语句,还能综合考虑多条SQL语句的优化效果,为DBA提供全面的决策支持。
44 11
|
21天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
61 18
|
20天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
22 7
|
19天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化与慢查询优化:原理与实践
通过本文的介绍,希望您能够深入理解MySQL索引优化与慢查询优化的原理和实践方法,并在实际项目中灵活运用这些技术,提升数据库的整体性能。
51 5
|
28天前
|
SQL 存储 缓存
MySQL进阶突击系列(02)一条更新SQL执行过程 | 讲透undoLog、redoLog、binLog日志三宝
本文详细介绍了MySQL中update SQL执行过程涉及的undoLog、redoLog和binLog三种日志的作用及其工作原理,包括它们如何确保数据的一致性和完整性,以及在事务提交过程中各自的角色。同时,文章还探讨了这些日志在故障恢复中的重要性,强调了合理配置相关参数对于提高系统稳定性的必要性。
|
26天前
|
SQL 关系型数据库 MySQL
MySQL 高级(进阶) SQL 语句
MySQL 提供了丰富的高级 SQL 语句功能,能够处理复杂的数据查询和管理需求。通过掌握窗口函数、子查询、联合查询、复杂连接操作和事务处理等高级技术,能够大幅提升数据库操作的效率和灵活性。在实际应用中,合理使用这些高级功能,可以更高效地管理和查询数据,满足多样化的业务需求。
103 3
|
29天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
1月前
|
SQL 存储 关系型数据库
MySQL进阶突击系列(01)一条简单SQL搞懂MySQL架构原理 | 含实用命令参数集
本文从MySQL的架构原理出发,详细介绍其SQL查询的全过程,涵盖客户端发起SQL查询、服务端SQL接口、解析器、优化器、存储引擎及日志数据等内容。同时提供了MySQL常用的管理命令参数集,帮助读者深入了解MySQL的技术细节和优化方法。