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

news2024/11/29 20:53:57

什么是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版本有很大的关系,不同版本的优化器的优化策略不同。

 

本文示例使用的数据库表2b6325b883e54caa8328af7f0c7bd40c.png

Explain命令(关键字)

 

explain简单示例

mysql>explain select * from t_user;6f6f9852ce384296bd96e246617483d5.png

 

在查询中的每个”表”会输出一行,这里的“表”的意义非常广泛,不仅仅是数据库表,还可以是子查询、一个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;d49b3315564543e48bd33c5714486059.png

 *注意,在资料收集过程中,发现不同版本的MySQL表现不一致,经反复对比,5.7及以后版本的输出如下:639402c3dcc248b88ef02bf8c7da1d6a.png

 

很显然,MySQL在这方面进行了优化.

 

*注意,MySQL不同版本Explain表现差异很大,有些场景,从语句层面看,是要使用到索引,但经过优化器分析,结合表中现有数据,如果MySQL认为全表扫描性能更优,则会使用全表扫描。

 

5)union:表明当前行对应的select是在 union 中的第二个和随后的 select

 

6)union result:表明当前行对应的select是从 union 临时表检索结果的 select

 

explain select 1 union all select 2 fromdual;dc20d6efa1734db6ad7a256b7be1065e.png

 MySQL5.7及以后同样做了优化5bf70c639534438a88e4788b6db11509.png

【table列】

 

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

【type列】

 

type列的结果表明当前行对应的select的关联类型或访问类型,也就是优化器决定怎么查找数据表中的行,以及查找数据行记录的大概范围。该列的取值优化程度的优劣,从最优到最差依次为:null>system> const > eq_ref > ref > range > index > ALL。一般来说,要保证查询达到range级别,最好达到ref。

 

1)null,MySQL优化器在优化阶段分解查询语句,在优化过程中就已经可以得到结果,那么在执行阶段就不用再访问表或索引。

explain select min(user_id) from t_user;73de6e3df5fc44858af8e55194dfe077.png

 

这时的函数min,在索引列user_id中选取最小值,可以直接查找索引来完成,不需要执行时再访问数据表。

 

2)const和system:const出现在用 primary key(主键) 或 unique key(唯一键) 的所有列与常数比较时,优化器对查询进行优化并将其部分查询转化成一个常量。最多有一个匹配行,读取1次,速度非常快。而system是const的特例,表中数据只有一条匹配时为system。此时可以用explain extended+show warnings查看执行结果。

 

explain extended select * from (select * from t_user where user_id = 1) tmp
show warnings;5fae1d0351244320b607439924288798.png972cddd2d422425c9dfe99aa6e657435.png 

MySQL5.7及以后版本优化后:136e937c13fa4452949443f4ba381a8b.png 

323db04dd7c847208c860687e4d81c7f.png 

 

3)eq_ref:primary key(主键)或 unique key(唯一键) 索引的所有构成部分被join使用 ,只会返回一条符合条件的数据行。这是仅次于const的连接类型。

 

explain select * from t_group_user gu left join t_group g ong.group_id = gu.group_id;

 

4) ref:与eq_ref相比,ref类型不是使用primary key(主键) 或 unique key(唯一键)等唯一索引,而是使用普通索引或者联合唯一性索引的部分前缀,索引和某个值相比较,可能会找到符合条件的多个数据行。

 

1. 如下示例,使用的group_name是普通索引

 

explain select * from t_group where group_name= 'group1';
9fa805cbf6744f4a9fd3f4f1d81330f2.png

 

2.关联表查询

 

explain select g.group_id from t_group gleft join t_group_user gu on gu.group_id = g.group_id;4148887cb6ed4c68b3308025dcbe035e.png

 

5)range:出现在 in(),between ,> ,<, >= 等操作符中。使用一个索引来查询给定范围的行。

 

6)index:扫描全表索引(index是从索引中读取的,所有字段都有索引,而all是从硬盘中读取),比ALL要快。

 

explain select * from t_group;cba926a2cada490b99df663297322c8b.png

 

7)all:即全表扫描,需要从头到尾去查找所需要的行。一般这种情况下这需要增加索引来进行查询优化了

 

explain select * from t_user;8c596fa5429a449dbfff201a8dc77be1.png

 

【possible_keys列】

 

这一列的结果表明查询可能使用到哪些索引。但有些时候也会出现出现possible_keys 列有结果,而 后面的key列显示 null 的情况,这是因为此时表中数据不多,优化器认为查询索引对查询帮助不大,所以没有走索引查询而是进行了全表扫描。 

 

如果possible_keys列的结果是null,则表明没有相关的索引。这时,可以通过优化where子句,增加恰当的索引来提升查询性能。

【key列】

 

这一列表明优化器实际采用哪个索引来优化对该表的访问。如果没有使用索引,则该列是 null。

【key_len列】

 

这一列表明了在索引里使用的字节数,通过这个值可以大致估算出具体使用了联合索引中的前几个列。 

key_len计算规则这里不再赘述,不同的数据类型所占的字节数是不一致的。

【ref列】

 

这一列表明了在key列记录的索引中,表查找值所用到的列或常量,常见的有:const(常量),字段名,如user.user_id

【rows列】

 

这一列表明优化器大概要读取并检测的行数。跟实际的数据行数大部分情况是不一致的。

【Extra列】

 

顾名思义,这一列表明的是额外信息,这一列的取值对优化SQL非常有参考意义。常见的重要取值如下: 

 

1)using index:所有被查询的字段都是索引列(称为覆盖索引),并且where条件是索引的前导列,出现这样的结果,是性能高的表现。

explainselect group_id,group_name from t_group;60d559519e6d4a66bf6b7981ccdf91d7.png

 

2)using where:被查询的列未被索引覆盖,where条件也并非索引的前导列,表示 MySQL 执行器从存储引擎接收到查询数据,再进行“后过滤”(Post-filter)。所谓“后过滤”,就是先读取整行数据,再检查此行是否符合 where 句的条件,符合就留下,不符合便丢弃。

explain select * from t_user whereuser_name='user1';663bdf8490514f109079f3d72e13f6c4.png

 

3)using where Using index:被查询的列被索引覆盖,并且where条件是索引列之一但是不是索引的前导列,也就是没有办法直接通过索引来查询到符合条件的数据

explain select * from t_group where group_name = 'group1';a121e0fbd9cb430ba79afd3e3a7d1048.png

 

4)null:被查询的列没有被索引覆盖,但where条件是索引的前导列,此时用到了索引,但是部分列未被索引覆盖,必须通过“回表查询”来实现,不是纯粹地用到了索引,也不是完全没用到索引

explain select * from t_user where user_id='1';c6e4cc6a8f7f428586e93f7f0258a0d9.png

5)using index condition:与using where类似,查询的列不完全被索引覆盖,where条件中是一个前导列的范围;这种情况未能通过示例显现,可能跟MySQL版本有关系。

 

6) using temporary:这表明需要通过创建临时表来处理查询。出现这种情况一般是要进行优化的,用索引来优化。创建临时表的情况:distinct,group by,orderby,子查询等

 

explain select distinct user_name from t_user;03ffe722cc204746ae8b7b48d1e06bf7.png

explain select distinct group_name fromt_group; --group_name是索引列8874e58392294a0cb90760430eff8924.png 

 

7) usingfilesort:在使用order by的情况下出现,mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。此时mysql会根据连接类型浏览所有符合条件的记录,并保存排序关键字和行指针,然后排序关键字并按顺序检索行信息。这种情况下要考虑使用索引来优化的。

 

explain select * from t_user orderby user_name;c95d2a7212ae45b7917e573d7e989b1b.png 

 explain select * from t_group order bygroup_name; --group_name是索引列62f5c9fcdbd84aa08a1554fb279ad476.png

 

查询优化建议

 

结合前面的描述,首先看 type列的结果,如果有类型是 all 时,表示预计会进行全表扫描(fulltable scan)。通常全表扫描的代价是比较大的,建议创建适当的索引,通过索引检索避免全表扫描。

 

再来看下 Extra 列的结果,如果有出现 Using temporary 或者 Using filesort 则要多加关注:

 

Using temporary,表示需要创建临时表以满足需求,通常是因为GROUP BY的列没有索引,或者GROUP BY和ORDER BY的列不一样,也需要创建临时表,建议添加适当的索引。

 

Using filesort,表示无法利用索引完成排序,也有可能是因为多表连接时,排序字段不是驱动表中的字段,因此也没办法利用索引完成排序,建议添加适当的索引。

 

Using where,通常是因为全表扫描或全索引扫描时(type 列显示为 ALL 或index),又加上了WHERE条件,建议添加适当的索引。

索引使用情况分析

数据库表

 

主键索引:demo_id

联合索引:c1,c2,c36a61ca16486647fe9f3a535870be4b41.png

 

实例说明

实例一:

explain select * from t_demo where c1='d1'and c2='d2' and c3='d3';

explain select * from t_demo where c2='d2'and c1='d1' and c3='d3';

explain select * from t_demo where c3='d3'and c1='d1' and c2='d3';52e16db939f14579974b40620a737787.png

几个Sql表现一致

type=ref,ref=const,const,const

执行常量等值查询时,改变索引列的顺序并不会更改explain的执行结果,优化器会进行优化,推荐按照索引顺序列编写sql语句。

 

实例二:

explain select * from t_demo where c1='d1'and c2>'d2' and c3='d3';

 

explain select * from t_demo where c1='d1'and c3>'d3' and c2='d2';

 

第一个例子范围右侧索引失效,使用到了两个索引。

第二个例子,由于优化器优化的原因,使用到了全部的三个索引。

实例三:

explain select * from t_demo wherec1>'c' and c2='d2' and c3='d3';

 

explain select * from t_demo wherec1>'e' and c2='d2' and c3='d3';

 

从上面两个实例可以发现,同样使用最左的索引列范围查询,有些情况未用到索引,做了全表扫描(第一个例子);有些情况使用到了索引(第二个例子)。

 

经反复验证,发现如下规律(不一定可靠),也可能与数据的第一行或最小值相关。

1. 跟存储的数据有关

2. 在大于条件下,如果条件数据小于列数据,则索引无效;如果条件数据大于列数据,则索引有效;

 

在设计查询条件时,请注意规避。

针对第一个例子,可以采用覆盖索引的方式优化。

实例四:

explain select * from t_demo where c1='d1'and c2='d2' order by c3;

 

explain select * from t_demo where c1='d1'order by c3;

 

explain select * from t_demo where c1='d1'and c3='d3' order by c2;

 

order by排序使用到索引和没使用到索引的情况

实例五:

explain select * from t_demo where c1='d1'and c4='d4' order by c1,c2;

 

条件列包含没有索引的列,出现了Using filesort

实例六:

explain select * from t_demo where c1='d1'and c4='d4' group by c1,c2;

 

性能非常差的场景,同时出现了Using temporary和Using filesort

总结

 

1. 两种方式的排序filesort和index,Usingindex是指MySQL扫描索引本身完成排序。index效率高,filesort效率低。

 

2. order by满足两种情况会使用Using index。

1)order by语句使用索引最左前列。

2)使用where子句与order by子句条件列组合满足索引最左前列。

 

3. 尽量在索引列上完成排序,遵循索引建立(索引创建的顺序)时的最佳左前缀法则。

 

4. group by与order by很类似,都是先排序后分组,遵照索引创建顺序的最佳左前缀法则。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1176553.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SAM 微调在医学上的尝试

1、2023下半年 1、 UNet与SAM结合的正确的道路SAMUS,一路SOTA没对手&#xff01; https://github.com/xianlin7/SAMUS 2、 本文提出 SonoSAM&#xff1a;一种用于分割超声图像上感兴趣对象的快速基础模型。 https://zhuanlan.zhihu.com/p/663988684 未开源 绿色是预测的&…

周大福开启“超越时光”天然钻石之旅,将非常钻石领入日常人生

&#xff08;2023年11月6日&#xff09;创立于1929年的周大福凭借独具匠心的设计、超凡卓越的品质和历史悠久的底蕴&#xff0c;成为了中国传统文化与现代审美相融合的知名珠宝品牌。周大福不仅在黄金珠宝领域声名显赫&#xff0c;在天然钻石方面也拥有独树一帜的专业实力。早在…

【广州华锐互动】3D全景虚拟旅游在文旅行业的应用场景

随着科技的不断发展&#xff0c;3D全景虚拟旅游正在成为一种新兴的旅游体验方式&#xff0c;它可以帮助旅游者更加深入地了解旅游信息&#xff0c;提升旅游体验。下面我们将详细介绍3D全景虚拟旅游可以应用于哪些场景。 一、旅游规划 3D全景虚拟旅游可以帮助旅游者更加直观地进…

Linux 本地Yearning SQL审核平台远程访问

文章目录 前言1. Linux 部署Yearning2. 本地访问Yearning3. Linux 安装cpolar4. 配置Yearning公网访问地址5. 公网远程访问Yearning管理界面6. 固定Yearning公网地址 前言 Yearning 简单, 高效的MYSQL 审计平台 一款MYSQL SQL语句/查询审计工具&#xff0c;为DBA与开发人员使用…

CDN加速:国内外价格与企业云服务最佳搭配方案

随着互联网的快速发展&#xff0c;CDN&#xff08;内容分发网络&#xff09;已经成为了企业提供高质量、高速度内容传递的不可或缺的工具。CDN通过将内容分发到离用户更近的服务器上&#xff0c;提高了网站性能&#xff0c;减少了加载时间&#xff0c;改善了用户体验。在本文中…

建表时如何合理选择字段类型

前言 我们在建表的时候关于字段类型的选择会有这么几类人&#xff1a; 严谨型 严格调研每个字段可能的大小&#xff0c;然后根据不同字段类型的限制&#xff0c;进行选择&#xff0c;这一类人在创建关系型数据表的时候是没有问题的。图自己省事型 把所有字段都设置为String&a…

硬件知识积累 共模电感的介绍

1. 基础知识了解 1. 共模电流(Common Mode Current)&#xff1a; 解释1&#xff1a;共模电流是不存在传导或有线回流通路的高频电流&#xff0c;共模电流与位移电流&#xff08;传导线路周边变化的电场&#xff09;一同组成环路实现电流闭合。 解释2: 共模电流是指通过电路的两…

GD32单片机远程升级下载,手机在线升级下载程序,GD32在线固件下载升级,手机下载程序固件方法

GD32、STM32单片机&#xff0c;是我们最常见的一种MCU。通常我们在使用STM32单片机都会遇到程序在线升级下载的问题。 GD32/STM32单片机的在线下载通常需要以下几种方式完成&#xff1a; 1、使用ST/GD提供的串口下载工具&#xff0c;本地完成固件的升级下载。 2、自行完成系统B…

自定义拖拽列表

效果图 DataAnalysis.vue <template><div class"app-container"><div class"operate"><el-select class"t_select" v-model"templateName" clearable placeholder"模版" size"default" cle…

电脑监控软件安装教程(30秒钟教会你快速安装)

在现代化办公中&#xff0c;如果有需要安装电脑监控软件的可以参考下面这篇文章&#xff1a; 一、准备阶段 可以自行到官网获取安装包&#xff0c;比如去域之盾官网&#xff0c;即可通过客服获取试用包。 二、操作阶段 1、这个就是安装包&#xff0c;点击运行。 2、这个是正…

Postgresql数据类型-数字类型

PostgreSQL支持的数字类型有整数类型、用户指定精度类型、浮点类型、serial类型。 PostgreSQL支持的数字类型如表所示 smallint、integer、bigint都是整数类型&#xff0c;存储一定范围的整数&#xff0c;超出范围将会报错。smallint存储2字节整数&#xff0c;字段定义时可写成…

大模型使用技巧

目录 1、文心一言&#xff1a;https://yiyan.baidu.com/ 2、智谱清言 ChatGLM&#xff1a;https://chatglm.cn/ 3、百川智能&#xff1a;https://www.baichuan-ai.com/ 4、科大讯飞星火大模型&#xff1a;https://xinghuo.xfyun.cn 5、字节跳动 AI 豆包 https://www.do…

idea2023 PoJie以后无法修改内存无效,heap内存设置

1. 打开电脑环境变量 2. 找到对应pojie文件 vmoptions目录 3. 修改这个文件 添加或者修改配置 -Xms128m -Xmx8192m4. 重启idea 修改成功

史上最全,从初级测试到高级测试开发面试题汇总,冲击大厂年50w+

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 接口测试面试相关…

考研408-计算机网络 第一章-计算机网络体系结构学习笔记及习题

第一章 计算机网络体系结构 一 计算机网络概述 1.1 概念及功能 1.1.1 计算机网络的概念 计算机网络就是互连的、自治的计算机系统的集合 互连&#xff1a;通过通信链路互联互通 自治&#xff1a;各个节点之间无主从关系&#xff0c;高度自治的 1.1.2 计算机网络的功能 功…

通过51单片机控制SG90舵机按角度正反转转动

一、前言 本文介绍如何通过51单片机控制SG90舵机实现角度的正反转转动。SG90舵机是一种常用的微型舵机&#xff0c;具有体积小、重量轻、结构简单等特点&#xff0c;被广泛应用于机器人、遥控模型和各种自动控制系统中。 使用51单片机&#xff08;STC89C52&#xff09;作为控…

公开IP属地信息如何保护用户的隐私?

公开IP属地信息通常涉及与用户或组织的隐私有关&#xff0c;因此在公开此类信息时需要非常小心&#xff0c;以避免侵犯他人的隐私权。以下是触碰底线的几种情况以及如何保护网络安全和用户隐私&#xff1a; 个人隐私保护&#xff1a; 公开IP属地信息可能泄露用户的物理位置&…

5虚拟局域网构建

前面简单介绍了使用交换机连接不同的服务器&#xff0c;这次我们看看怎么搞虚拟局域网。 虚拟局域网&#xff0c;也被称为VLAN&#xff08;Virtual Local Area Network&#xff09;&#xff0c;是一个网络的划分概念&#xff0c;使得一组网络设备可以表现得像在同一个物理网络…

大家都在用的数据安全运维管理系统是哪家?有什么功能?

随着数字化大力发展&#xff0c;越来越多的企业开始重视数据安全&#xff0c;开始采购数据安全运维管理系统。但面对市面上多个品牌的数据安全运维管理系统&#xff0c;企业采购时候往往是蒙圈的。因此不少负责人在问&#xff0c;大家都在用的数据安全运维管理系统是哪家&#…

时间序列预测模型实战案例(八)(Informer)个人数据集、详细参数、代码实战讲解

论文地址->Informer论文地址PDF点击即可阅读 代码地址-> 论文官方代码地址点击即可跳转下载GIthub链接 本文介绍 本篇博客带大家看的是Informer模型进行时间序列预测的实战案例&#xff0c;它是在2019年被提出并在ICLR 2020上被评为Best Paper&#xff0c;可以说Inform…