当前位置: 首页 > news >正文

MySQL实战之深入浅出索引(下)

1.前言

在上一篇文章中,我们介绍了InnoDB索引的数据结构模型,今天我们再继续聊一下跟MySQL索引有关的概念。

在介绍之前,我们先看一个问题:

表初始化语句


mysql> create table T (
ID int primary key,
k int NOT NULL DEFAULT 0, 
s varchar(16) NOT NULL DEFAULT '',
index k(k))
engine=InnoDB;insert into T values(100,1, 'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');

如果我们执行select * from T where k between 3 and 5,需要执行几次树的搜索操作,会扫描多少行?

下面是该表的索引数据结构
在这里插入图片描述
1.在k索引树上找到k=3的记录,取得ID=300
2.在到ID索引树查到ID=300对应的行记录
3.在k索引树去下一个值k=5,取得ID=500
4.再回到ID索引树查到ID=500对应的行记录
5.在k索引树取下一个值k=6,不满足条件,循环结束

在这个过程中,回到主键索引树搜索的过程,叫做回表。可以看到,查询过程读了k索引树的3条记录(步鄹1、3和5),回表了两次(2和4)

在这个例子中,由于查询结果所需要的数据只在主键索引上有,所以不得不回表。那么,有没有可能经过索引优化,避免回表过程呢?

2.覆盖索引

假设执行的语句是select ID from T where k between 3 and 5,这时只需要查ID的值,而ID的值在k索引树了,因此可以直接提供查询结果,不需要回表。也就是说,在这个查询里面,索引k已经覆盖了查询的需求,称之为覆盖索引

由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。

需要注意的是,在引擎内部使用覆盖索引在索引k上其实读取了三个记录,但是对于MySQL的server层来说,它就是找引擎拿到了两条记录,因此MySQL认为扫描行数是2.

基于上面覆盖索引,我们来讨论一个问题:在一个市民信息表,是否有必要将身份证号和名字简历联合索引?
市民表的建表语句


CREATE TABLE `tuser` (`id` int(11) NOT NULL,`id_card` varchar(32) DEFAULT NULL,`name` varchar(32) DEFAULT NULL,`age` int(11) DEFAULT NULL,`ismale` tinyint(1) DEFAULT NULL,PRIMARY KEY (`id`),KEY `id_card` (`id_card`),KEY `name_age` (`name`,`age`)
) ENGINE=InnoDB

我们知道,身份证号是市民的唯一标识,也就是说,如果根据身份证号查询市民信息的需求,我们只要在身份证号字段上建立索引就够了。而再建立一个(身份证号、姓名)的联合索引,是不是浪费空间?

如果现在有一个高频请求,要根据市民的身份证号查询他的姓名,这个联合索引就有意以了。它可以在这个高频请求上用到覆盖索引,不再需要回表查整行记录,减少语句的执行时间。

当然,索引字段的维护总是有代价的。因此,在建立冗余索引来支持覆盖索引时就需要权衡考虑了

3.最左前缀原则

看到这里你一定有一个疑问,如果为每一种查询都设计一个索引,索引是不是太多了。如果我现在要按照市民的身份证号去查他的家庭地址呢?虽然这个查询需求在业务中出现的概率不高,但总不能让它走全表扫描吧?反过来说,单独为一个不频繁的请求创建一个(身份证号,地址)的索引又感觉有点浪费,mysql应该怎么做呢?

我们先说结论,B+树这种索引结构,可以利用索引的最左前缀,来定位记录。

为了直观的说明这个概念,我们用(name,age)这个联合索引来分析。
在这里插入图片描述
可以看到,索引项是按照索引定义里面出现的字段顺序排序的。

当你的逻辑需求是查到所有名字是张三的人时,可以快速定位到ID4,然后向后遍历得到所有需要的结果。

如果你要查的是所有第一个字是张的人,你的SQL语句的条件是where name like ”张%“。这时,你也能够用上这个索引,查找到第一个符合条件的记录是ID3,然后向后遍历直到不满足条件为止。

可以看到,不只是索引全部定义,只要满足最左前缀,就可以利用索引来加快检索。这个最左前缀可以是联合索引的最左N个字段,也可以是字符串索引的最左N个字符。

基于上面对最左前缀索引的说明,我们来讨论一个问题:在建立联合索引的时候,如何安排索引内的字段顺序。

这里我们的评估标准是,索引的复用能力。因为支持最左前缀,所以当已经有了(a,b)这个联合索引后,一般就不需要单独在a上建立索引了。因此,第一原则是,如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的

所以现在知道了,这篇开头的问题里,我们要为高频请求创建(身份证号,姓名)这个联合索引,并用这个索引支持根据身份证号查询地址的需求。

那么如果既有联合查询,又有基于a、b各自查询的呢?查询条件里面只有b的语句,是无法使用(a,b)这个联合索引的,这时候你就不得不维护另外一个索引b。

这时候,我们就要考虑的原则就是空间了。比如上面这个市民表的情况,name字段是比age字段大的,那我就建议创建一个(name,age)的联合索引和一个(age)的索引。

4.索引下推

上面我们说了最左前缀原则,如果遇到不满足最左前缀的部分,又会怎么样呢?

我们还是以市民表的联合索引(name,age)为例。如果我现在有一个需求:检索出表中名字第一个字是张,并且年龄是10岁的所有男孩,SQL书写如下

select * from tuser where name like "张%" and age = 10 and ismale = 1;

我们已经知道了最左前缀原则,上面的SQL语句,只能用张,找到第一个满足条件的记录ID3。

然后呢?

当然是判断其他条件是否满足。

在MySQL5.6之前,只能从ID3开始一个个回表。到主键索引上找出数据行,在对比字段值。

而MySQL5.6引入了索引下推优化,可以在索引变量过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。下图是两个执行的过程图
在这里插入图片描述
在这里插入图片描述
上面每个虚线箭头标识回表一次。

第一个图,在(name,age)索引里面我特意去掉了age的值,这个过程InnoDB并不会去看age的值,只是按顺序把name第一个字是张的记录一条条取出来回表。因此需要回表4次。

第二个图,InnoDB在(name,age)索引内部就判断了age是否等于10,对于不等于10的记录,直接判断并跳过。这这个例子中,只需要对ID4、ID5这两条记录回表取数据判断,只需要回表2次。

5.小结

今天这篇文章,我们讨论了InnoDB索引的一些概念,包括覆盖索引、前缀索引、索引下推。可以看到,在满足语句需求的情况下,尽量少的访问资源是数据库设计的重要原则之一。我们在使用数据库的时候,尤其是在设计表结构时,也要以减少资源消耗作为目标

相关文章:

MySQL实战之深入浅出索引(下)

1.前言 在上一篇文章中,我们介绍了InnoDB索引的数据结构模型,今天我们再继续聊一下跟MySQL索引有关的概念。 在介绍之前,我们先看一个问题: 表初始化语句 mysql> create table T ( ID int primary key, k int NOT NULL DEFA…...

(二分查找)leetcode1539. 第 k 个缺失的正整数

文章目录一、题目1、题目描述2、基础框架3、原题链接二、解题报告1、思路分析2、时间复杂度3、代码详解三、本题小知识一、题目 1、题目描述 给你一个 严格升序排列 的正整数数组 arr 和一个整数 k 。 请你找到这个数组里第 k 个缺失的正整数。 示例 1: 输入&…...

yaml文件格式详解及实例

🍁博主简介 🏅云计算领域优质创作者   🏅华为云开发者社区专家博主   🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 文章目录yaml简介yaml语法规则Yaml语法实例数组…...

AOP在PowerJob中的使用,缓存锁保证并发安全,知识细节全总结

这是一篇简简单单的文章,需要你简简单单看一眼就好,如果有不明白的地方,欢迎留言讨论。 在之前的文章中出现过一次AOP的使用,就是在运行任务之前,需要判断一下,触发该任务执行的server,是不是数…...

对账平台设计

背景 随着公司业务的蓬勃发展,交易履约清结算业务的复杂性也在不断的增高,资金以及各种数据的一致性和准确性也变得越发重要。 以交易链路为例,存在着如下一些潜在的不一致场景: 订单支付成功了,但是订单状态却还是“…...

JavaEE进阶第五课:SpringBoot的创建和使用

上篇文章介绍了Bean 作用域和生命周期,这篇文章我们将会介绍SpringBoot的创建和使用 目录1.为什么要学习StringBoot1.1什么是SpringBoot1.2SpringBoot的优点2.如何用Idea创建SpringBoot项目3.项目目录介绍和运行3.1输入Helloworld结尾1.为什么要学习StringBoot 在前…...

我带过的一名C++实习生——Z同学

刚开始带Z同学,吃饭聊天时,我顺便了解了下他的擅长:linux平台下C、C网络编程。 接下来的实习,主要分为两个阶段:小组公共培训和项目实训。 小组公共培训为期2周,主要学习和了解公司文化制度,讲师…...

面试题13. 机器人的运动范围

面试题13. 机器人的运动范围 难度:middle\color{orange}{middle}middle 题目描述 地上有一个 mmm 行 nnn 列的方格,从坐标 [0,0][0,0][0,0] 到坐标 [m−1,n−1][m-1,n-1][m−1,n−1] 。一个机器人从坐标 [0,0][0, 0][0,0] 的格子开始移动,它…...

LeetCode189_189. 轮转数组

LeetCode189_189. 轮转数组 一、描述 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,…...

java Files和Paths的使用详解 附有使用demo

前言 Java Files和Paths是Java 7中引入的新API,用于处理文件和目录。Files类提供了许多有用的静态方法来操作文件和目录,而Path类则表示文件系统中的路径。 创建文件和目录 在Java中创建文件和目录非常简单。我们可以使用Files类的createFile()方法和…...

如何使用ApacheTomcatScanner扫描Apache Tomcat服务器漏洞

关于ApacheTomcatScanner ApacheTomcatScanner是一个功能强大的Python脚本,该脚本主要针对Apache Tomcat服务器安全而设计,可以帮助广大研究人员轻松扫描和检测Apache Tomcat服务器中的安全漏洞。 功能介绍 1、支持使用多线程Worker搜索Apache Tomcat服…...

js中的定时器 setTimeout()和setInterval()

JavaScript 定时器,有时也称为“计时器”,用来在经过指定的时间后执行某些任务,类似于我们生活中的闹钟。 在 JavaScript 中,我们可以利用定时器来延迟执行某些代码,或者以固定的时间间隔重复执行某些代码。例如&…...

【吃透Js】深入学习浅拷贝和深拷贝

一、JavaScript数据类型原始类型对象类型二、原始类型和对象类型的区别1.原始类型2.引用类型3.复制4.比较5.值传递三、浅拷贝概念实现方法四、深拷贝概念五、浅拷贝、深拷贝和赋值的区别浅拷贝和赋值六、小结想要真正搞明白深浅拷贝,你必须要熟练掌握赋值、对象在内…...

AUTOSAR为啥要开发新的社区商业模式?

总目录链接>> AutoSAR入门和实战系列总目录 文章目录1 自适应平台架构中的集群更新1.1 ara::diag 服务(诊断)更新1.2 信号到服务映射和自动驾驶接口让我们讨论一下信号到服务映射服务:Automated Driving Interface:2 车载应用商店概念本文介绍Re…...

数据结构和算法面试常见题必考以及前端面试题

1.数据结构和算法 1.1 反转单向链表 public class Node {public int value;public Node next; }public Node reverseList(Node head) {Node pre null;Node next null;while (head ! null) {next head.next;head.next pre;pre head;head head.next}return pre; }1.2 在顺…...

一文解决Python所有报错

前言 Python是一种强大的编程语言,但是它也有一些报错,这些报错可能会让你感到困惑。本文将介绍如何解决Python中的常见报错。 首先,让我们来看看Python中最常见的报错:SyntaxError。这种报错表明你的代码中有语法错误&#xff0c…...

LeetCode 1237. Find Positive Integer Solution for a Given Equation【双指针,二分,交互】

本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...

【C语言】结构体进阶

一、结构体 1. 结构体的声明 (1) 结构的基础知识 结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。(2)结构的声明 struct tag {member-list; }variable-list;例如描述一个学生&#x…...

全志T3+FPGA国产核心板——Pango Design Suite的FPGA程序加载固化

本文主要基于紫光同创Pango Design Suite(PDS)开发软件,演示FPGA程序的加载、固化,以及程序编译等方法。适用的开发环境为Windows 7/10 64bit。 测试板卡为全志T3+Logos FPGA核心板,它是一款基于全志科技T3四核ARM Cortex-A7处理器 + 紫光同创Logos PGL25G/PGL50G FPGA设计…...

深度学习之 imgaug (图像增强)学习笔记

深度学习之 imgaug (图像增强)前言1\. 安装和卸载2\. 示例2.1 基本使用2.2 包含常用的变换示例3 Augmenters常用函数3.1 iaa.Sequential()3.2 iaa.someOf()3.3 iaa.OneOf()3.4 iaa.Sometimes()3.5 iaa.WithColorspace()3.6 iaa.WithChannels()3.7 iaa.No…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

【JavaEE】-- HTTP

1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...