mysql explain学习记录
参考了公司内相关博客,实践并记录下,为后面分析并优化索引做准备。
MySQL explain命令是查看MySQL查询优化器如何执行查询的主要方法,可以很好的分析SQL语句的执行情况。
每当遇到执行慢(在业务角度)的SQL,都可以使用explain检查SQL的执行情况,并根据explain的结果相应的去调优SQL等。
github链接: mysql explain学习
一、准备表
# 建表
CREATE TABLE single_table (id INT NOT NULL AUTO_INCREMENT,key1 VARCHAR(100),key2 INT,key3 VARCHAR(100),key_part1 VARCHAR(100),key_part2 VARCHAR(100),key_part3 VARCHAR(100),common_field VARCHAR(100),PRIMARY KEY (id),KEY idx_key1 (key1),UNIQUE KEY idx_key2 (key2),KEY idx_key3 (key3),KEY idx_key_part(key_part1, key_part2, key_part3)
) Engine=InnoDB CHARSET=utf8;CREATE TABLE tmp (id INT NOT NULL AUTO_INCREMENT,key1 VARCHAR(100),key2 INT,key3 VARCHAR(100),key_part1 VARCHAR(100),key_part2 VARCHAR(100),key_part3 VARCHAR(100),common_field VARCHAR(100),PRIMARY KEY (id),KEY idx_key1 (key1),UNIQUE KEY idx_key2 (key2),KEY idx_key3 (key3),KEY idx_key_part(key_part1, key_part2, key_part3)
) Engine=InnoDB CHARSET=utf8;# 生成一些数据
# 定义存储过程
DROP PROCEDURE IF EXISTS proc_initData;
DELIMITER $
CREATE PROCEDURE proc_initData()
BEGINDECLARE i INT DEFAULT 1;WHILE i<=10000 DOinsert into single_table(key1,key2,key3,key_part1,key_part2,key_part3,common_field) VALUES(substring(md5(rand()),1,15),floor(10000000 * rand()),substring(md5(rand()),1,15),substring(md5(rand()),1,15),substring(md5(rand()),1,15),substring(md5(rand()),1,15),substring(md5(rand()),1,15));SET i = i+1;END WHILE;
END $
delimiter ;# 上面定义存储过程后,可能会有key冲突,可以多执行几次,生成较多测试数据
CALL proc_initData();
二、测试
mysql> EXPLAIN SELECT * FROM single_table\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: single_tablepartitions: NULLtype: ALL
possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 6896filtered: 100.00Extra: NULL
对结果分析:
列名 | 说明 |
---|---|
id | 标识select所属的行。如果有子查询,会顺序编号 |
select_type | 显示本行是简单或复杂select |
table | 表名 |
type | 针对单表的访问方法 |
possible_keys | 可能用到的索引 |
key | 实际用的索引 |
key_len | 实际使用索引里占用的字节数 |
ref | 当使用索引列为等值查询时,对应的匹配信息 |
rows | 预估需要读取的行数,估算值不精确 |
Extra | 额外信息 |
2.1 id
给SELECT语句分配的id,因为我们的SQL语句可能包括多个查询,比如有子查询,连表查询,像这样
mysql> EXPLAIN SELECT * FROM single_table WHERE key1 in (SELECT key1 FROM single_table where key2 > 'a')\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: single_tablepartitions: NULLtype: ALL
possible_keys: idx_key1key: NULLkey_len: NULLref: NULLrows: 6896filtered: 100.00Extra: Using where
*************************** 2. row ***************************id: 1select_type: SIMPLEtable: <subquery2>partitions: NULLtype: eq_ref
possible_keys: <auto_distinct_key>key: <auto_distinct_key>key_len: 303ref: sql_test.single_table.key1rows: 1filtered: 100.00Extra: NULL
*************************** 3. row ***************************id: 2select_type: MATERIALIZEDtable: single_tablepartitions: NULLtype: ALL
possible_keys: idx_key2,idx_key1key: NULLkey_len: NULLref: NULLrows: 6896filtered: 100.00Extra: Using where
3 rows in set, 2 warnings (0.41 sec)
为啥有三行?第一行和第二行都是1,第三行是2,这是为啥呢?跟接下来的select_type有点关系。
2.2 select_type
上面2.1的示例输出了三行,每行代表一个查询语句,select_type就是每行查询语句的类型,select_type的可选项比较多:
2.2.1、SIMPLE
查询语句中不包含UNION或者子查询的查询都算作是SIMPLE类型;连接查询也是这个类型
2.2.2、MATERIALIZED
上面示例的第三行就是这个类型,表明查询优化器把子查询物化成表了,第二行的table是就是这个物化表,前两行的id都是1,说明他们是连接查询,属于一个查询语句。
2.2.3、PRIMARY
对于包含UNION、UNION ALL或者子查询的大查询来说,它是由几个小查询组成的,其中最左边的那个查询的select_type值就是PRIMARY
EXPLAIN SELECT * FROM single_table UNION SELECT * FROM tmp;
2.2.4、UNION
对于包含UNION或者UNION ALL的大查询来说,它是由几个小查询组成的,其中除了最左边的那个小查询以外,其余的小查询的select_type值就是UNION
2.2.5、UINON RESULT
MySQL选择使用临时表来完成UNION查询的去重工作,针对该临时表的查询的select_type就是UNION RESULT
2.2.6、其他
此外还有很多选项,有兴趣可以单独去了解。
3.3 partitions
忽略
2.4、type
查询一个数据,我们可以全表捞出来,然后再一条条对比找到这条数据,也可以通过索引马上得到它,这就是访问方式的不同,type就是表明使用了哪种访问方式,它也有很多选项,我们选其中一些来说:
2.4.1、const
当查询条件为主键或唯一键的等值匹配,就是这种类型,这种类型查询贼快。
EXPLAIN SELECT * FROM single_table where id=1;
2.4.2、eq_ref
在连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的方式进行访问的,被驱动表的查询方式就是这个
EXPLAIN SELECT * FROM single_table INNER JOIN tmp ON single_table.id = tmp.id;
2.4.3、ref
当通过普通的二级索引列与常量进行等值匹配时来查询某个表,那么对该表的访问方法就可能是ref
EXPLAIN SELECT * FROM single_table WHERE key1 = 'a';
2.4.4、index_merge
有些情况下会使用索引合并的查询,即使用多个索引进行查询,然后将结果合并
EXPLAIN SELECT * FROM single_table WHERE key1 = 'a' OR key3 = 'a';
2.4.5、range
使用索引字段的范围查询
EXPLAIN SELECT * FROM single_table WHERE key1 IN ('a', 'b', 'c');
2.4.6、index
有联合索引时,但是我们查询条件只包含联合索引的右边某个字段,造成没法走这个联合索引,需要全表扫描,index表明走该联合索引全表扫描而不是走聚簇索引全表扫描,为啥呢?
因为聚簇索引包含完整数据,二级索引只包含索引字段和主键列,更加轻量,全表扫描二级索引的成本更低。
EXPLAIN SELECT key_part2 FROM single_table WHERE key_part3 = 'a';
2.4.7、All
也就是全表扫描,危险信号!!!
2.5、possible_keys和key
possible_keys表示可能用到的索引,key表示实际使用索引。
EXPLAIN SELECT * FROM single_table WHERE key1 > 'z' AND key3 = 'a';
key1和key3都有索引,实际使用了key3的索引。MySQL会记录一些统计信息,查询优化器会判断使用哪个索引的成本更低就使用哪个索引。
2.6、key_len
实际使用索引的最大长度,单位字节。比如上面示例显示key_len是303个字节。咋算出来的呢?该字段是varchar(100),然后是utf8,utf8字符集是三个字节,
则是100*3=300,然后该字段可以为NULL,则需要一个字节作为标志位,并且因为是varchar类型,所以需要2个字节记录它的实际长度,所以是300+1+2=303.
2.7、ref
ref表明在通过索引进行等值比较时,跟索引比较的值的类型是什么。
EXPLAIN SELECT * FROM single_table WHERE key1 = 'a';
这里的key1=‘a’,'a’就是个常量,所以是const。还有其他类型就自行了解吧。
2.8、rows
如果是走索引,表示本次查询的扫描索引记录数;如果是全表扫描,表示全表记录数。看执行计划时,这个字段也是需要重点关注的。
2.9、Extra
额外的说明信息,种类比较多,只说几个吧,全面的文档在这:https://dev.mysql.com/doc/refman/8.0/en/explain-output.html
2.9.1、Using index
当我们的查询列和索引条件是同一个列,就是这个情况。啥意思呢?我们知道二级索引值存储了二级索引列和主键值,当查询列只包括二级索引列(或也有主键),则不需要回表查询聚簇索引了。
这也告诉我们,查询列尽量指明我们想要的列,如果查询条件是二级索引,查询列也是只有二级索引列(或也有主键),就能提升一定性能。
EXPLAIN SELECT key1 FROM single_table WHERE key1 = "2";
2.9.2、Using where
参考:https://segmentfault.com/q/1010000003094577
1、查询条件没有索引或索引字段被函数修饰造成索引失效,走全表扫描了;
2、有时会出现"Using where; Using index"或"Using index condition; Using where"的情况,意思就是通过索引查出了数据,然后再通过where条件过滤掉不符合条件的记录。
3、这个提示跟走没走索引没有关系,可以不用太纠结。知道它是用来过滤返回个客户端的数据的就行。
2.9.3、Using index condition
跟"Using index"一样,走索引了,但是涉及到的字段有些不在二级索引里,需要走一遍聚簇索引才能查到。
2.9.4、Impossible WHERE
where条件始终是false,不会命中任何记录,比如你的条件是“where 1 != 1"
2.9.5、Impossible WHERE noticed after reading const tables
1、用主键或唯一键查询时,查询一条不存在的记录。
2、关于"const"的解释:https://dev.mysql.com/doc/refman/8.0/en/explain-output.html#jointype_const
三、索引失效的一些场景
1、通过二级索引查找时,还是查出了太多数据,这个时候如果需要回表去查聚簇索引就会有随机IO,造成性能低下,这样MySQL可能会直接走聚簇索引的全表扫描。
2、对索引字段用MySQL函数做了处理,比如我们对createTime建了索引,但是用的时候用date_format()包装了一下,也会使索引失效。
或者下列的情形:
SELECT * FROM single_table WHERE binary key1 = 'c90ab6cb630a35f';
3、模糊搜索时,使用了like “%xxx”的形式,因为MySQL的索引是左匹配的。
4、在使用联合索引时,必须带上最左边的字段(也是左匹配原则),比如a,b,c字段建立联合索引,则(a=x and b=x)和(a=x and c=x)都是走索引的,但是(b=x) (b=x and c=x)是不走索引的。
5、虽然是索引字段,但是使用了"not in"
EXPLAIN SELECT * FROM single_table WHERE key1 not in ("22");
6、使用"or"联系一个索引字段和一个非索引字段
EXPLAIN SELECT key1 FROM single_table WHERE key1 = 'a' or common_field = 'a';
索引失效的场景比较多,这里只归纳了部分:
相关文章:

mysql explain学习记录
参考了公司内相关博客,实践并记录下,为后面分析并优化索引做准备。 MySQL explain命令是查看MySQL查询优化器如何执行查询的主要方法,可以很好的分析SQL语句的执行情况。 每当遇到执行慢(在业务角度)的SQL,…...

电压放大电路的作用有哪些(电压放大器)
电压放大电路是电子电路中常见且重要的组件,其主要作用是将输入信号的电压放大到所需的输出电压级别,并保持输入信号的形状和准确度。电压放大电路广泛应用于各种电子设备和系统中,具有以下几个重要的作用: 信号放大:电…...

编译opencv-3.4.5 [交叉编译]
在unbuntu20.04环境下编译opencv3.4.5, cmake 版本:3.27.4 gcc 版本:11.4.0 g版本:11.4.0 在此环境下编译opencv4.5.4正常。 1. 编译时遇到的问题 (1) Built target libprotobuf make: *** [Makefile:163…...

Canal 实现MySQL与Elasticsearch7数据同步
1 工作原理 canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送 dump协议 MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal ) canal 解析 binary log 对象(原始为 byte 流) 优点&…...

网络安全攻防对抗之隐藏通信隧道技术整理
完成内网信息收集工作后,渗透测试人员需要判断流量是否出得去、进得来。隐藏通信隧道技术常用于在访问受限的网络环境中追踪数据流向和在非受信任的网络中实现安全的数据传输。 一、隐藏通信隧道基础知识 (一)隐藏通信隧道概述 一般的网络通…...
读书笔记:多Transformer的双向编码器表示法(Bert)-2
多Transformer的双向编码器表示法 Bidirectional Encoder Representations from Transformers,即Bert; 第2章 了解Bert模型(掩码语言模型构建和下句预测) 文本嵌入模型Bert,在许多自然语言处理任务上表现优秀&#…...

Python 基于PyCharm断点调试
视频版教程 Python3零基础7天入门实战视频教程 PyCharm Debug(断点调试)可以帮助开发者在代码运行时进行实时的调试和错误排查,提高代码开发效率和代码质量。 准备一段代码 def add(num1, num2):return num1 num2if __name__ __main__:f…...

spring security auth2.0实现
OAuth 2.0 的认证/授权流程 jwt只是认证中的一步 4中角色 资源拥有者(resource owner)、客户端(client 第三方)、授权服务器(authorization server)和资源服务器(resource server)。…...
MySQL(6)LOCK和MVCC
一、锁的分类 按照锁的属性:读锁、写锁、共享锁、排它锁、悲观锁、乐观锁 按照锁的范围:表锁、页锁、间隙锁、临键锁、行锁 按照锁的作用:意向锁、意向共享锁、意向排它锁、IS锁、IX锁 二、MySQL为什么要有锁 锁是计算机协调多个进程或线程并…...

最新IDE流行度最新排名(每月更新)
2023年09月IDE流行度最新排名 顶级IDE排名是通过分析在谷歌上搜索IDE下载页面的频率而创建的 一个IDE被搜索的次数越多,这个IDE就被认为越受欢迎。原始数据来自谷歌Trends 如果您相信集体智慧,Top IDE索引可以帮助您决定在软件开发项目中使用哪个IDE …...

I2C的上拉电阻如何计算?
说明: 1、本文只说明I2C上拉电阻的最小值如何计算。 2、I2C最小值和最大值计算的详细原理可以参考这篇文章:https://mp.weixin.qq.com/s/ZvJJ0rPRd_STULj8g1H81A。 3、I2C最小值的计算方式比较简单,在实际应用中计算出最小值,然后…...
Centos下安装 oracle11g 博客2
[oraclewangmengyuan database]$ ./runInstaller -silent -responseFile /home/oracle/database/response/db_install.rsp -ignorePrereq ./runInstaller -silent -responseFile /home/oracle/database/response/db_install.rsp -ignorePrereq 正在启动 Oracle Universal Insta…...

记一次逆向某医院挂号软件的经历
背景 最近家里娃需要挂专家号的儿保,奈何专家号实在过于抢手,身为程序员的我也没有其他的社会资源渠道可以去弄个号,只能发挥自己的技术力量来解决这个问题了。 出师不利 首先把应用安装到我已经 Root 过的 Pixel 3 上面,点击应…...

Canal实现Mysql数据同步至Redis、Elasticsearch
文章目录 1.Canal简介1.1 MySQL主备复制原理1.2 canal工作原理 2.开启MySQL Binlog3.安装Canal3.1 下载Canal3.2 修改配置文件3.3 启动和关闭 4.SpringCloud集成Canal4.1 Canal数据结构
Kafka的消息传递保证和一致性
前言 通过前面的文章,相信大家对Kafka有了一定的了解了,那接下来问题就来了,Kafka既然作为一个分布式的消息队列系统,那它会不会出现消息丢失或者重复消费的情况呢?今天咱们就来一探。 实现机制 Kafka采用了一系列机…...
Docker 部署 Firefly III 服务
拉取最新版本的 Firefly III 镜像: $ sudo docker pull fireflyiii/core:latest在本地预先创建好 upload 和 export 目录, 用于映射 Firefly III 容器内的 /var/www/html/storage/upload 和 /var/www/html/storage/export 目录。 使用以下命令来运行 Firefly III …...

配置OSPFv3基本功能 华为笔记
1.1 实验介绍 1.1.1 关于本实验 OSPF协议是为IP协议提供路由功能的路由协议。OSPFv2(OSPF版本2)是支持IPv4的路由协议,为了让OSPF协议支持IPv6,技术人员开发了OSPFv3(OSPF版本3)。 无论是OSPFv2还是OSPFv…...

【AI视野·今日Sound 声学论文速览 第九期】Thu, 21 Sep 2023
AI视野今日CS.Sound 声学论文速览 Thu, 21 Sep 2023 Totally 1 papers 👉上期速览✈更多精彩请移步主页 Interesting: 📚Auto-ACD,大规模文本-音频数据集自动生成方法。 基于现有的大模型和api构建了一套大规模高质量的音频文本数据收集方法,…...

数据结构-----堆(完全二叉树)
目录 前言 一.堆 1.堆的概念 2.堆的存储方式 二.堆的操作方法 1.堆的结构体表示 2.数字交换接口函数 3.向上调整(难点) 4.向下调整(难点) 5.创建堆 6.堆的插入 7.判断空 8.堆的删除 9.获取堆的根(顶)元素 10.堆的遍历…...

set/multiset容器、map容器
目录 set/multiset容器 set基本概念 set大小和交换 set插入和删除 查找和统计 set和multiset的区别 改变set排序规则 set存放内置数据类型 set存放自定义数据类型 pair队组 map容器 map容器的基本概念 map构造和赋值 map大小和交换 map插入和删除 map查找和统计…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...