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数据结构是支持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查找和统计…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据,你需要完成以下配置步骤: ✅ 一、在 SQL Server 端配置(服务器设置) 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到:SQL Server 网络配…...
Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...
LangChain【6】之输出解析器:结构化LLM响应的关键工具
文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器?1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...
Python[数据结构及算法 --- 栈]
一.栈的概念 在 Python 中,栈(Stack)是一种 “ 后进先出(LIFO)”的数据结构,仅允许在栈顶进行插入(push)和删除(pop)操作。 二.栈的抽象数据类型 1.抽象数…...
