【MySQL】Explain执行计划(十七)

2024-09-03 16:52

本文主要是介绍【MySQL】Explain执行计划(十七),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

🚗MySQL学习·十七站~
🚩本文已收录至专栏:MySQL通关路
❤️每章节附章节思维导图,文末附全文思维导图,感谢各位点赞收藏支持~
⭐学习汇总贴,超详细思维导图:【MySQL】学习汇总(完整思维导图)

一.引入

当我们需要对SQL语句进行优化时必须先分析其性能时,EXPLAIN是一个不可或缺的神器,它可以帮助我们获取 MySQL 如何执行 SELECT 语句的信息,例如

  • 表如何连接和连接的顺序
  • 哪些索引可以使用
  • 是否使用了索引
  • 实际使用了哪些索引
  • 扫描的数据行数

通过使用Explain执行计划可以说一条SQL语句的“身体状况”完全展现在我们眼前了,借此便可以着手分析它的"健康状况",并为它开出“诊断方案”,最后"实施救治"。

Explain执行计划的使用非常简单,只需要在执行的SQL语句前面加上Explain即可,例如:

Explain 待执行的SQL语句

例如执行如下SQL:

explain select * from user where id = 1668983497699696641;

可以看到如下结果:

在这里插入图片描述

这就是SQL语句的“身体状况”说明书概述:

字段含义
idSelect查询的序列号,表示查询中执行select子句或者是操作表的顺序 (id相同,执行顺序从上到下;id不同,值越大,越先执行)
select_type表示 SELECT 的类型,常见的取值有 SIMPLE(简单表,即不使用表连接 或者子查询)、PRIMARY(主查询,即外层的查询)、 UNION(UNION 中的第二个或者后面的查询语句)、 SUBQUERY(SELECT / WHERE之后包含了子查询)等
table使用的是哪张表
partitions分区表命中的分区情况
type数据扫描类型,性能由好到差的连接类型为NULL、system、const、 eq_ref、ref、range、 index、all
possible_key在这张表上可能会使用到的索引,一个或多个
key实际使用的索引,如果为NULL,则没有使用索引
key_len表示索引中使用的字节数, 该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下, 长度越短越好
ref表查找值所用到的字段名或常量
rows预计需要扫描的行数,在innodb引擎的表中,是一个估计值, 可能并不总是准确的
filtered表示返回结果的行数占需读取行数的百分比, filtered 的值越大越好
extra执行过程中一些特殊情况补充说明信息

接下来我们就来一起详细解读一下这张说明书,学习一下如何分析它的症状,其中需要重点关注的是typeextra 列,至于如何“救治”那当然是交给你啦~

二.id

表示Select查询的序列号,表示查询中执行Select子句或者是操作表的顺序

id相同,执行顺序从上到下;id不同,值越大,越先执行

例如,我们执行带子查询的SQL,子查询语句id往往是较大的,表示其先执行。

在这里插入图片描述

三.select_type

表示Select的类型,常见的取值有:

  • SIMPLE:简单表,即不使用表连接 或者 子查询
  • PRIMARY:主查询,即当查询中包含子查询时,最外层的查询被标记为 PRIMARY
  • UNIONUNION 中的第二个或者后面的查询语句
  • SUBQUERYSELECT / WHERE之后包含了子查询

例如,下面SQL语句中,外层查询为PRIMARY主查询,WHERE之后所包含的查询为SUBQUERY子查询。

在这里插入图片描述

四.table

表示使用的是哪张表

例如,外层查询使用了post表,子查询使用了user表。

在这里插入图片描述

五.partitions

表示分区表命中的分区情况,如果表没有进行分区,或者查询没有命中任何分区(例如全表扫描),则该列的值通常为 NULL

补充

当数据表中的数据量很大时,为了提高操作的效率,可能会对表进行分区操作。
所谓的分区就是将一个表分解成多个区块进行操作和保存,从而降低每次操作的数据,提高性能,而对应用来说是透明的,从逻辑上看就只是一个表(这里跟分库分表的访问不一样),但是物理上的这个表可能是由多个物理分区组成,每个分区都是一个独立的对象,可以进行独立处理。

六.type(重要)

表示数据扫描类型通常用来衡量SQL的执行效率,性能由好到差的连接类型为:

  • null:一般不太可能优化到NULL,除非在查询的时候不访问任何表,比如Select ‘A’

  • system:一般出现在访问系统表时

  • const(结果只有一条的主键或唯一索引扫描):表示该表最多有一个匹配记录,一般出现在使用主键或者唯一索引访问时

  • eq_ref(唯一索引扫描):通常出现在联表的情况下,表示主键索引或唯一索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录

  • ref(非唯一索引扫描):一般出现在使用非唯一性索引访问时,可能会匹配到多个记录

  • range(索引范围扫描):一般出现在对索引字段进行范围匹配,比如使用 < 、>、in、between 等关键词

  • index(全索引扫描):只遍历索引树,且只从索引树中获取数据

  • all(全表扫描):表示该查询将遍历全表以找到匹配行,这是最糟糕的一种查询方式

range开始,索引的作用会越来越明显,因此我们需要尽量让 SQL 查询可以使用到 range 这一级别及以上的 type 访问方式。例如,将用作查询条件的字段设置为索引、思考能否设置为唯一索引…

例如,针对下述post表的userId创建了非唯一索引,因此在查询post表时选择了ref非唯一索引扫描,而user的id字段为主键,选择了const级别扫描。

在这里插入图片描述

七.possible_key

表示在这张表上可能会使用到的索引,一个或多个,不代表一定会使用到。

例如,查询涉及到的字段存在联合索引和其他类型索引,优化器将根据所执行的SQL语句选择一个合适的进行使用。

八.key

表示实际使用的索引,如果为NULL,则没有使用索引。

通常,我们在查询条件中使用到了索引字段,该列都会显示所使用到的索引名称。如果使用了索引字段,但是此处显示为NULL,排除mysql估计使用索引比全表扫描更慢的情况,就要仔细想一下索引使用的是不是有问题,例如命中了索引失效的常见几种情况:联合索引非最左匹配、对索引使用函数、左或左右模糊匹配…

九.key_len

表示索引中使用的字节数, 该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下, 长度越短越索引效果好。

通常情况下,**我们可以根据key_len来判断联合索引是否完全生效。**例如,key显示使用到了联合索引,但是key_len显示的字节数与联合索引实际字节数不符合时,说明只使用到了部分索引。

十.ref

表示表查找值所用到的字段名或常量。通常值为:const(常量),func,NULL,字段名(post.userId)

例如,下述1和2都为const表示用到的为常量(1668904042690179073)。

在这里插入图片描述

十一.rows

表示预计需要扫描的行数。,在innodb引擎的表中,是一个估计值, 可能并不总是准确的。通常,较小的 rows 值通常表示查询效率较高,因为这代表需要处理的数据量较少。

例如,对于一个简单的根据主键进行查询的操作,rows 值通常会很小,可能为 1 ,因为通过主键可以直接定位到唯一的一行数据。

相反,如果一个查询没有使用合适的索引或者索引无法有效地过滤数据,rows 值可能会很大。

比如,一个没有合适索引的全表扫描查询,rows 值可能等于表中的总行数。

十二.filtered

表示**返回结果的行数占需读取行数的百分比, filtered 的值越大越好。**它表示在根据索引条件进行初步筛选后,还需要对结果集进行进一步筛选以得到最终结果的比例。

  • 较高的 filtered 值(接近 100%)通常表示通过索引条件已经能够很好地筛选出接近最终结果的行,这可能意味着查询的效率相对较高。
  • 较低的 filtered 值(例如 10% 或更低)则可能表示在初步筛选后,还需要对大量的行进行进一步的筛选,这可能会影响查询的性能。

十三.extra

表示执行过程中一些特殊情况补充说明信息,例如:

  • Using filesort :当查询语句中包含 order by 操作,而且无法利用索引完成排序操作的时候, 这时不得不选择相应的排序算法进行,甚至可能会通过文件排序,效率是很低的,所以要避免这种问题的出现。

  • Using temporary:使了用临时表保存中间结果,MySQL 在对查询结果排序时使用临时表,常见于排序 order by 和分组查询 group by。效率低,要避免这种问题的出现。

  • Using index:所需数据只需在索引即可全部获得,不须要再到表中取数据,也就是使用了覆盖索引,避免了回表操作,效率不错。

  • Using where:表示 MySQL 在存储引擎检索行后,需要应用 WHERE 子句来过滤结果。

  • Backward index scan:表示 MySQL 正在以相反的方向,即从后往前扫描索引,在大多数情况下,正向的索引扫描通常更有效率,出现反向索引可能扫描影响了查询性能。

十四.全文概览

在这里插入图片描述

这篇关于【MySQL】Explain执行计划(十七)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1133501

相关文章

SQL中的外键约束

外键约束用于表示两张表中的指标连接关系。外键约束的作用主要有以下三点: 1.确保子表中的某个字段(外键)只能引用父表中的有效记录2.主表中的列被删除时,子表中的关联列也会被删除3.主表中的列更新时,子表中的关联元素也会被更新 子表中的元素指向主表 以下是一个外键约束的实例展示

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

如何去写一手好SQL

MySQL性能 最大数据量 抛开数据量和并发数,谈性能都是耍流氓。MySQL没有限制单表最大记录数,它取决于操作系统对文件大小的限制。 《阿里巴巴Java开发手册》提出单表行数超过500万行或者单表容量超过2GB,才推荐分库分表。性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL配置、数据表设计、索引优化。500万这个值仅供参考,并非铁律。 博主曾经操作过超过4亿行数据

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

MySQL高性能优化规范

前言:      笔者最近上班途中突然想丰富下自己的数据库优化技能。于是在查阅了多篇文章后,总结出了这篇! 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份

[MySQL表的增删改查-进阶]

🌈个人主页:努力学编程’ ⛅个人推荐: c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构,刷题刻不容缓:点击一起刷题 🌙心灵鸡汤:总有人要赢,为什么不能是我呢 💻💻💻数据库约束 🔭🔭🔭约束类型 not null: 指示某列不能存储 NULL 值unique: 保证某列的每行必须有唯一的值default: 规定没有给列赋值时的默认值.primary key:

MySQL-CRUD入门1

文章目录 认识配置文件client节点mysql节点mysqld节点 数据的添加(Create)添加一行数据添加多行数据两种添加数据的效率对比 数据的查询(Retrieve)全列查询指定列查询查询中带有表达式关于字面量关于as重命名 临时表引入distinct去重order by 排序关于NULL 认识配置文件 在我们的MySQL服务安装好了之后, 会有一个配置文件, 也就

maven 编译构建可以执行的jar包

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~ 专栏导航 Python系列: Python面试题合集,剑指大厂Git系列: Git操作技巧GO

Java 连接Sql sever 2008

Java 连接Sql sever 2008 /Sql sever 2008 R2 import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class TestJDBC