一文带你了解SQL的执行计划(explain)
一. 什么是SQL执行计划
为什么关注sql的执行计划,因为一个sql的执行计划可以告诉我们很多关于如何优化sql的信息 。
通过一个sql计划,如何访问中的数据 (是使用全表扫描还是索引查找?)
一个表中可能存在多个表中不同的索引,表中的类型是什么是否子查询、关联查询等…
sql学习来自于sqlercn讲师
- 了解SQL如何访问表中的数据
- 了解SQL如何使用表中的索引
- 了解SQL所使用的查询类型
二. 获取SQL执行计划
在sql前加上explain
关键词就可以了!
在MySQL8.0中是支持对select/delete/inster/replace/update
语句来分析执行计划
而MySQL5.6前只支持对select
语句分析执行计划。
提示: replace语句是跟inster语句非常类似,只是插入的数据和表中存在的数据(存在主键或者唯一索引)冲突的时候,replace语句会把原来的数据替换新插入的数据,表中不存在唯一的索引或主键,则直接插入新的数据
除了静态分析,MySQL8.0还可以使用for connection
来直接分析正在执行的sql。(connection_id 就是processlist表中的数据id
)
三. 分析执行计划
执行计划内容分析
例子1:课程人数大于3000
EXPLAIN
select course_id,title,study_cnt
from imc_course
where study_cnt > 3000;
访问得出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ulVz8LR1-1660528543156)(https://blog.97it.net/usr/uploads/2021/07/976069882.png)]
这些字段代表什么含义呢?
四. 分析执行计划(ID列)
- ID标识查询执行的顺序
- ID相同时,由上到下分析执行
- ID不同时,由大到下分析执行
ID列中的值只能有2中情况,要么是1组数字,要么是NULL
如果ID为数字序列,则说明查询的SQL语句对数据对象的操作顺序
如果是NULL,则代表数据由另外的2个查询union操作后所产生的结果集。
例子2: 【ID一致】学习人数大于3000人的课程id、课程分类、难度、课程标题、课程学习人数
explain
select course_id,class_name,level_name,title,study_cnt
from imc_course a
join imc_class b on b.class_id=a.class_id
join imc_level c on c.level_id =a.level_id
where study_cnt > 3000
返回3行结果,并且ID值是一样的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4fRE2eQF-1660528543157)(https://blog.97it.net/usr/uploads/2021/07/3819973405.png)]
由上往下读取sql的执行计划,第一行是table
c表作为驱动表 ,等于是以C表为基础来进行循环嵌套的一个关联查询。 (4 *100*1 =400 总共扫描400行等到数据)
SQL优化器根据表的统计信息来进行数据的调整,实际上是由C表作为主表进行嵌套查询,sql优化动态的来调整表的关联顺序。
例子3: 【ID不一致】查询课程表中不存在课程章节的数据
explain
select
a,course_id,a.title
from imc_course a
where a.course_id not in (select course_id from imc_chapter b
)
五. 分析执行计划(select_type列)
值 | 含义 |
---|---|
SIMPLE | 不包含子查询或者UNION操作的查询(简单查询) |
PRIMARY | 查询中如果包含任何子查询,那么最外层的查询则被标记为PRIMARY |
SUBQUERY | select列表中的子查询 |
DEPENDENT SUBQUERY | 依赖外部结果的子查询 |
UNION | union操作的第二个或之后的查询只为union |
DEPENDENT UNION | 当union作为子查询时,第二或是第二个后的查询的select_type值 |
UNION RESULT | union产生的结果集 |
DERIVED | 出现在from子句中的子查询 (派生表) |
例子1 : 查询学习人数大于3000 合并 课程是MySQL的记录
EXPLAIN
SELECT
course_id,class_name,level_name,title,study_cnt
FROM imc_course a
join imc_class b on b.class_id =a.class_id
join imc_level c on c.level_id = a.level_id
WHERE study_cnt > 3000unionSELECT course_id,class_name,level_name,title,study_cnt
FROM imc_course a
join imc_class b on b.class_id = a.class_id
join imc_level c on c.level_id = a.level_id
WHERE class_name ='MySQL'
先看id等于2
id=2 则是查询mysql课程的sql信息,分别是b,a,c
3个表,是union操作,selecttype为是UNION
id=1 为是查询学习人数3000人的sql信息,是primary操作的结果集,分别是c,a,b
3个表,select_type为PRIMARY
最后一行是NULL, select_type是union RESULT
代表是2个sql 组合的结果集。
六. 分析执行计划(table列)
指明是从那个表中获取数据
<table name>
就展示数据库表名 (如果表取了别名就显示别名)
<unionM,N>
由ID为M,N 查询union产生的结果集
<derived N>/<subquery N>
由ID为N的查询产生的结果(通常也是一个子查询的临时表)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LWAjTCVy-1660528543160)(https://blog.97it.net/usr/uploads/2021/07/1972183977.png)]
七. 分析执行计划(partition列)
- 对于查询分区表,显示查询的分区ID
- 对于非分区表,显示NULL
八. 分析执行计划(type列)【重要】
注意的: 是在mysql中不一定是使用JOIN才算是关联查询,实际上mysql会认为每一个查询都是连接查询
就算是查询一个表,对mysql来说也是关联查询。
type的取值是体现了mysql访问数据的一种方式。
type列的值按照性能高到低排列 system
> const
> eq_ref
> ref
> ref_or_null
> index_merge
> range
> index
> ALL
值 | 含义 |
---|---|
system |
这是const连接类型的特例,当查询的表只有一行时使用
|
const |
表中有且只有一个匹配 的行时使用,如对主键或唯一索引的查询 ,这是效率最高的链接方式
|
eq_ref |
唯一索引或主键查询 ,对应每个索引建,表中只有一条记录与之匹配 【A表扫描每一行B表只有一行匹配满足】
|
ref |
非唯一索引查找,返回匹配某个单独值的所有行
|
ref_or_null | 类似于ref类型的查询,但是附加了对NULL值列的查询 |
index_merge |
该链接类型表示使用了索引合并优化方法
|
range |
索引范围扫描 ,常见于between、>、< 这样的查询条件
|
index |
FULL index Scan全索引扫描 ,同ALL的区别是,遍历的是索引树
|
ALL |
FULL TABLE Scan全表扫描 ,这是效率最差的链接方式
|
举例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N9NTW3u2-1660528543160)(https://blog.97it.net/usr/uploads/2021/07/649653009.png)]
拿以上的sql语句分析
这里先分析ID不同,由大到小,ID相同由上到下。
- 「ID=1 union , select_type= PRIMARY 」C表 就是imc_level
作为驱动主表
,a表level_id没加索引,他是ALL
是全表扫描的,没有一个可用的索引。 - 「ID=1 , select_type= PRIMARY 」 ,a表 就是imc_course,a表class_id加了索引,但是没where去查询,并且数量量小也会走全表扫描, 也是
ALL
全表扫描,没有一个可用的索引。` - 「 ID=1 , select_type= PRIMARY 」 ,
b表 就是imc_class
, a表class_id加了索引跟class表的主键对应, 是eq_ref
对应每个索引建,表中只有一条记录与之匹配,嵌套循环查找,B表通过A表的class_id关联查找。 【一条记录匹配】 - 「 ID=2 , select_type= union 」,
b表就是imc_class
,是const
,因为where加了条件class_name=MySQL
,而class_name加了唯一索引,并且只匹配到一个。 【只有一行】 - 「 ID=2 , select_type= union 」 a表就是imc_course表,也是用到索引。
匹配某个单独值的所有行
- union是结果集,没有索引也是通过全表扫描。
如果
where like "MySQL%"
,会是什么type类型?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wTdfjfhB-1660528543161)(https://blog.97it.net/usr/uploads/2021/07/1304606973.png)]
虽然class_name 加了索引
,但是使用where的like% 右配
所以会走索引范围扫描
。
如果
where like "%MySQL%"
, 会是什么type类型 ?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6w7Nr2G5-1660528543161)(http://blog.97it.net/usr/uploads/2021/07/536036482.png)]
虽然class_name 加了索引
,但是使用where的%like% 左右统配
所以会走全索引扫描
,如果不加索引的话,左右统配会走全表扫描。
九. 分析执行计划(possible_keys/key/key_len/ ref 列)
possible_keys
说明表可能用到了哪些索引,而key
是指实际上使用到的索引。基于查询列和过滤条件进行判断。
查询出来都会被列出来,但是不一定会是使用到。
- 指出查询中可能会用到的索引
- 指出查询时实际用到的索引
- 实际使用索引的最大长度
possible_keys / key
可能用到的索引
如果在表中没有可用的索引,那么key列
展示,possible_keys
是NULL,这说明查询到覆盖索引。
key_len
实际用到的索引
key_len
是索引使用的字节数ken_len
注意的是,在联合索引中,如果有3列,那么总字节是长度是100个字节的话,那么key_len
值数据可能少于100字节,比如30个字节,这就说明了查询中并没有使用联合索引的所有列。而只是利用到某一些列或者2列。- key_len的长度是由表中的定义的字段长度来计算的,并不是存储的实际长度,所以满足数据最短的实际字段存储,因为会直接影响到生成执行计划的生成 。
ref
指出那些列或常量被用于索引查找
执行 select * from imc_user where user_id=1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8gQhxQ15-1660528543162)(http://blog.97it.net/usr/uploads/2021/07/1123411536.png)]
从头到尾看下
首先他的ID列是1 ,代表就是数据库操作对象,并不是union产生的结果集
select_type列是SIMPLE
是代表简单的查询
查询所涉及的表table列是imc_user
表,由于这不是一个分区表所以partitions列是等于NULL 。
type列是const
是个常量查询,固定值是1 ,只匹配一个并且用到的索引是主键索引。
possible_keys列 可能用到的索引也是主键索引,key列 实际索引也是主键索引。因为user_id是主键
key_len列 长度是4个字节,user_id是int类型,大小也是4个字节
ref列 是const
也就是一个固定值,固定的常量值来进行索引过滤的。
十. 分析执行计划(rows / filtered 列)
rows列
( 有2个含义)1.、根据统计信息预估的扫描行数,
2、另一方面是关联查询内嵌的次数,每获取匹配一个值都要对目标表查询,所以循环次数越多性能越差。
因为扫描行数的值是预估的,所以并不准确
执行 select * from imc_user where user_id=1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HU1I5Fj7-1660528543162)(http://blog.97it.net/usr/uploads/2021/07/2916774700.png)]
拿以上举例,因为查询是一条记录,所以row是一条数据。
filtered列
表示返回结果的行数占需读取行数的百分比
filtered列跟rows列是有关联的,是返回预估符合条件的数据集,再去取的行的百分比。也是预估的值。
数值越高查询性能越好
十一. 分析执行计划(Extra列)
包括了不适合在其他列中所显示的额外信息
值 | 含义 |
---|---|
Distinct | 优化distinct操作,在找到第一匹配的元组后即停止找同样值的动作 |
Not exists | 使用not exists来优化查询 |
Using filesort |
使用文件来进行排序,通常会出现在order by 或 group by 查询中
|
Using index | 使用了覆盖索引进行查询**【意思是查询所需要的信息用索引来获取,不需要对表进行访问】** |
Using temporary |
MySQL需要使用临时表来处理,常见于排序、子查询、和分组查询
|
Using where |
需要在MySQL服务器层使用WHERE条件来过滤数据
|
select tables optimized away | 直接通过索引来获取数据,不用访问表 |
例子1:查询课程表没有章节的信息
EXPLAIN
select a.course_id,title
from imc_course a
left join imc_chapter b on b.course_id = a.course_id
where b.course_id is null
可以看到a表的key列
是有值的,而possible_keys
是NULL,代表是采用了覆盖索引。印证了Extra列
是Using index 覆盖索引
【优化】 a表这个索引key是
title
,如果加了where条件可以优化a表的type级别。比如where tite ='xxx' or where title like "Mysql%"
。
而b表是type列
是ref级别,匹配某个单独值的所有行,并且加了where条件。所以再Extra列
是有多个的。
以上就完成分析计划所以列的说明了…
一文带你了解SQL的执行计划(explain)相关推荐
- 不带参数的SQL语句执行方法
不带参数的SQL语句执行方法 以下是不带参数的SQL语句执行方法的代码,它调用通用数据访问类(SqlHelper)执行 SqlHelper.ExecuteNonQuery()方法,使用示例为; int ...
- 一文搞定 SQL Server 执行计划
导读 数据开发过程中,开发完成的 SQL 发布到生产环境,经常会发生 SQL 执行慢甚至根本无法执行,如何避免这种情况呢?这一篇我们分析一下 SQL Server 的执行计划是如何生成及如何阅读评估执 ...
- SQL Server 执行计划缓存
原文:SQL Server 执行计划缓存 标签:SQL SERVER/MSSQL SERVER/数据库/DBA/内存池/缓冲区 概述 了解执行计划对数据库性能分析很重要,其中涉及到了语句性能分析与存储 ...
- PostgreSQL查询当前执行中SQL的执行计划——pg_show_plans
点击上方"蓝字" 关注我们,享更多干货! 执行计划存储 如果同样的SQL要执行很多遍,且每次都是同样的执行计划.每次都发生硬解析,则会消耗大量时间.类似于Oracle存放执行计划的 ...
- oracle的sql执行计划语句,最权威Oracle获取SQL语句执行计划大全
该文档为根据相关资料整理.总结而成,主要讲解Oracle数据库中,获取SQL语句执行计划的最权威.最正确的方法.步骤,此外,还详细说明了每种方法中可选项的意义及使用方法,以方便大家和自己日常工作中查阅 ...
- EXPLAIN PLAN获取SQL语句执行计划
一.获取SQL语句执行计划的方式 1. 使用explain plan 将执行计划加载到表plan_table,然后查询该表来获取预估的执行计划 2. 启用执行计划跟踪功能,即autotrace功能 3 ...
- Oracle 查看sql语句执行计划方法
注意这篇文章只介绍查看sql语句执行计划的方法, 并不是说明如何看懂执行计划. 一般来讲, 直接在sqlplus 执行 set autotrace on; 就可以了 其前提是登陆用户必须有视图 v_ ...
- 剖析SQL Server执行计划
-->Title: 淺議SQL Server执行计划 -->Author: wufeng4552 -->Date :2009-10-20 15:08:24 前言: 最近溫習了執行計劃 ...
- oracle 删除列 大数据_Oracle 删除指定sql的执行计划。
1. oracle10g以前我们都是直接刷新共享池,但这样数据库中所有sql的执行计划都会被删掉.这种办法也不可取,下面简单介绍一下这种办法: 测试版本: SQL> select * from ...
- 在 MySQL 中使用 explain 查询 SQL 的执行计划(转自: 数据分析与开发)
**来源:Oo若离oO my.oschina.net/ruoli/blog/1807394** 1.什么是MySQL执行计划 要对执行计划有个比较好的理解,需要先对MySQL的基础结构及查询基本原理有 ...
最新文章
- 数据挖掘学习笔记--决策树C4.5
- python离线包安装_python 通过pip freeze、dowload打离线包及自动安装的过程详解(适用于保密的离线环境...
- codeigniter文件上传问题
- 自研芯片鸿蒙系统,华为智慧屏:自研智慧芯片鸿蒙系统 9月发布
- 网络管理的任务包括linux,网络管理员的任务是阻止的10.152.8.0/21 一个基于Linux的防火墙的网络子网的默认端口上的所有出站SSH 连接。以下哪项规则集将完成这项任务?(单选题)...
- jsp页面执行java语法,获取的值在页面调用
- 电脑没有声音显示未启用音频输出设备怎么处理
- 两个栈实现一个队列(图解),一看就懂
- 基于Java Swing五子棋小游戏设计和实现
- wps中将文档输出为pdf_如何将WPS文件转换为PDF格式
- pyautogui入门学习之消息盒子
- animate.css 梦幻西游动画
- CTF竞赛进阶 (一) 密码学
- matlab中ljnspace,Matlab图像感兴趣区域编码
- 用云开发搭建的微信答题小程序v1.0
- 教你如何写好一篇专利申请?
- 获取图片上任意一点的颜色值
- OK6410A移植mw150us无线网卡驱动
- LRU Cache 缓存
- C#将数字自动翻译为中文
热门文章
- 暴风影音2011 去广告补丁V1.1
- 乘风破浪,遇见未来新能源汽车(Electric Vehicle)之特斯拉提车必须知道的十个流程
- 不用找,你想要的凹凸贴图素材都在这里
- 计算机二级vfp考试怎么学,计算机二级VFP考试基础教程(7)
- 解密后的暴风一号病毒(1KB文件夹快捷方式病毒)
- oracle sql优化的几种方法
- electron中加载html,electron页面加载函数loadFile
- 设置session时间 php,php中设置session过期时间方法
- CANape 20拍了拍你,更新速递请查收~
- 脑力大挑战,1分钟 Serverless 部署“线上魔方”赢魔方