首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MySQL的索引是怎么加速查询的?

MySQL的索引是怎么加速查询的?

作者头像
敖丙
发布于 2020-02-24 09:03:56
发布于 2020-02-24 09:03:56
2.8K00
代码可运行
举报
文章被收录于专栏:三太子敖丙三太子敖丙
运行总次数:0
代码可运行

昨天讲到了索引的基础知识,没看的小伙伴记得看:

《爱上面试官》系列-数据库索引

MySQL 的索引长什么样子?索引到底是怎么加速查询的?

事实上,在你还没有执行 create index 语句的时候,MySQL 就已经创建索引了。

让我们从建表开始吧。

1、聚簇索引

执行建表语句:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE TABLE `student` (
  `id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL COMMENT '主键id',
  `student_no` VARCHAR(64) COMMENT '学号',
  `name` VARCHAR(64) COMMENT '学生姓名',
  `age` INT COMMENT '学生年龄',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8mb4 COMMENT='学生信息表';

插入 5 条数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
insert into student(student_no,name,age) values(101,"Alice",18);
insert into student(student_no,name,age) values(102,"Bob",19);
insert into student(student_no,name,age) values(104,"Brandt",15);
insert into student(student_no,name,age) values(105,"David",19);
insert into student(student_no,name,age) values(109,"David",18);

在插入的过程中,MySQL 会用你指定的主键,在这里是递增主键,维护起一棵 B+树,我用了旧金山大学做的 BPlusTree Visualization 来模拟这棵树的样子,主键从 1 开始递增,插入五条,所以是 1 到 5:

如果有时间,也建议你到这个网站去,从 1 到 5,一个一个插入,你会看到 B+树在插入的过程中是怎么维护它的几个特性的:

  • 有序:左边节点比右边小
  • 自平衡:左右两边数量趋于相等
  • 节点分裂:节点在遇到元素数量超过节点容量时,是如何分裂成两个的,这个也是 MySQL 页分裂的原理
  • ……

插句题外话,MySQL 里绝大多数索引都是 B+树,另外有少数情况会使用 Hash索引、R-tree等等,今天只讨论 B+树。

模拟工具只支持插入一个值,所以你看不到主键之外的其他数据,实际上,这棵 B+树的叶子节点是带有行的全部数据的,所以我又自己画了张完整的图:

如果没有这棵 B+树,你要根据主键查询,比如

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select * from student where id = 5;

对不起,数据是无序的,你只能全表扫描,犹如大浪淘沙。

有同学会说主键不是递增的吗,那不就可以用二分法来查找?不是的,主键虽然是递增的,但是如果你写入磁盘时,没有去维护有序数组这样一个数据结构(比如你删掉了 4,怎么把 5 往前面挪),那数据在磁盘里依旧是无序的,查找时只能随机查找,而如果你维护了有序数组这样的数据结构,其实也是建了索引,只是建了不一样的数据结构的索引罢了。 至于为什么 MySQL 选择了 B+树,而不用上面说的有序数组、hash索引等,咱们后面再聊。

现在有了这棵 B+树,数据被有规律的存储起来,查找 id=5,也不再大浪淘沙,而是变得很有章法:

  • 从上到下,先找到 3,5 比它大,找右节点
  • 接着找到 4,发现 5 还是比它大,继续找右节点
  • 这次到达叶子节点了,叶子节点是一个递增的数组,那就用二分法,找到 id=5 的数据

你要访问磁盘的次数,是由这棵树的层数决定的。为了方便说明,我在文章里举的例子的数据量不会太大,所以用不用索引,性能提升的效果不明显,但是你可以脑补下大数据量的画面。

如果你没有指定主键呢?没关系,唯一键也可以。

连唯一键也没有?也没关系,mysql会给你建一个rowid字段,用它来组织这棵 B+树.

反正 MySQL 就一个目的,数据要有规律的存储起来,就像之前在 数据库是什么 里说的,数据是否被规律的管理起来,是数据库和文件系统区分开来的重要因素。

这个 MySQL 无论如何都会建起来,并且存储有完整行数据的索引,就叫聚簇索引(clustered index)。

2、二级索引

聚簇索引只能帮你加快主键查询,但是如果你想根据姓名查询呢?

对不起,看看上面这棵树你就知道,数据并没有按照姓名进行组织,所以,你还是只能全表扫描。

不想全表扫描,怎么办?那就给姓名字段也加个索引,让数据按照姓名有规律的进行组织:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
create index idx_name on student(name);

这时候 MySQL 又会建一棵新的 B+树:

你会发现这棵树的叶子节点,只有姓名和主键ID两个字段,没有行的完整数据,这时候你执行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select * from student where name = "David";

MySQL 到你刚刚创建的这棵 B+树 查询,快速查到有两条姓名是“David”的记录,并且拿到它们的主键,分别是 4 和 5,但是你要的是select *呀,怎么办?

别忘了,MySQL 在一开始就给你建了一棵 B+树 了,把这两棵树,放在一起,拿着从这棵树上查到的两个主键ID,去聚簇索引找,事情不就解决了?

这个不带行数据完整信息的索引,就叫二级索引(secondary index),也叫辅助索引。

3、复合索引

继续,如果我还想根据姓名和年龄同时查询呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select * from student where name = "David" and age = 18;

还是那个道理,数据虽然按照 name 有规律的组织了,但是没有按照 age 有规律组织,所以我们要给 nameage 同时建索引:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
create index idx_name_age on student(name,age);

这时候 MySQL 又会建一棵 B+树,这下 B+树 的节点里面,不只有 name,还有 age 了:

注意观察我用红色虚线框出来的那两个节点,这是这棵树和上面那棵只给 name 建索引的树的唯一区别,两个元素换了个位,因为排序时,是先用 name 比较大小,如果 name 相同,则用 age 比较。

还是那句话,这里举的例子数据量很少,你可以想象下有一万个叫“David”的学生,年龄随机分布在 13 到 20 之间,这时候如果没有按照 age 进行有规律的存储,你还是得扫描一万行数据。

4、未完待续

写到这,我想起之前大学的一个学霸,人家考高数前都在背公式,他却在纸上练习这些公式的推导过程,纸上写的密密麻麻,当时不解,现在回想起来,这实在是降维打击。

别人都只会用公式,他却时刻牢记这些公式是怎么来的,别人考试就只会套用公式,他却可以用这些公式以外的知识解决问题。

MySQL 索引也是,很多人都知道索引就像字典的目录,索引是 B+树,但是如果只知道这些,又有什么用呢?

知识是需要往深里学,才能转化为能力的,你知道的多,并不代表你能解决的问题就多,反而那些知道的没那么多,但是对他知道的东西,都研究透彻的人,才能一通百通。

当你知道了 MySQL 的索引长成这个样子后,还用去背什么“最左匹配”吗?

随便问个问题,只给 student 表建 idx_name_age 这个复合索引,这两个 sql 语句,会走索引吗?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select * from student where name = "David";
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select * from student where age = 18;

照着上面这几张图,你几乎可以推导出一切,什么样的 sql 能走索引,什么样的 sql 不能。

甚至,这么精妙的数据结构设计,难道就只能用来加速查询吗?

至少现在我能想到的,索引可以拿来干的事情,就至少有四种。

下次聊。

(吐血画图,此处应该点赞)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 敖丙 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Xcode11打包失敗IPA processing failed
是因为项目中使用的SDK支持i386,x86_86這個架构,可能是iOS13不支持模拟器架构了,所以必须强制去除。
用户6094182
2019/11/06
5K0
ios 13 xcode 11打包 IPA processing failed
大概意思是:我用的FMDB.framework 里面 x86_64 i386 之类的 ,终端命令行删除 就可以 !
用户1437675
2020/07/03
9130
ipa送审Unsupported Architectures问题处理
问题 送审时反馈: ERROR ITMS-90087: "Unsupported Architectures. The executable for xxx.app/Frameworks/xxxx.framework contains unsupported architectures '[i386, x86_64]'." ERROR ITMS-90209: "Invalid Segment Alignment. The app binary at 'xxx.app/Frameworks/xxxx.fra
freesan44
2020/06/19
2.4K0
代码管理| 手把手教你封装自己的静态库SDK
这里重点说下,怎样饮用Bundle中的图片资源。这里使用的是简写:@"JWJFramework.bundle/open"其中JWJFramework.bundle是Bundle的名称。
進无尽
2018/09/12
1.6K0
代码管理| 手把手教你封装自己的静态库SDK
iOS 了解Xcode Bitcode
看了以上内容,我们就可以对Bitcode有一个简单的了解了。那么如果我们项目中在使用某些Framework或.a的时候,遇到了类似笔者遇到的错误的时候,我们就需要查看所用的Framework或.a是否支持bitcode。
且行且珍惜_iOS
2022/05/13
1.1K0
iOS 了解Xcode Bitcode
Xcode常用的配置
Header Search Paths与User Header Search Paths
码客说
2019/10/22
2K0
Xcode 常见 CLI 工具
在咱们日常开发中,或多或少都会用到 Xcode 内置的一些CLI工具,但是大部分小伙伴可能只是会用到一些具体的命令,今天我们就一起来聊一聊 Xcode 内置的常见Command Lines Tool。
CoderStar
2022/09/23
4.2K0
iOS_Apple 指令集
​ ARM架构,过去称作高级精简指令集机器(英语:Advanced RISC Machine,更早称作艾康精简指令集机器,Acorn RISC Machine),是一个精简指令集(RISC)处理器架构家族,其广泛地使用在许多嵌入式系统设计。由于节能的特点,其在其他领域上也有很多作为。ARM处理器非常适用于移动通信领域,符合其主要设计目标为低成本、高性能、低耗电的特性。
mikimo
2022/07/20
1.4K0
【IOS开发进阶系列】Framework制作专题
http://blog.csdn.net/yongyinmg/article/details/41513917
江中散人_Jun
2023/10/16
7390
【IOS开发进阶系列】Framework制作专题
iOS逆向之Mach-O文件
阅读笔者的其他文章,我们了解了编译过程中的预处理、词法分析、语法分析、编译、链接等步骤。经常和编译型语言打交道的开发者对于可执行文件的编译过程肯定不陌生。我们用 Xcode 构建一个程序的过程中,会把源文件 (.m 和 .h) 文件转换为一个可执行文件。这个可执行文件中包含的字节码将会被 CPU (iOS 设备中的 ARM 处理器或 Mac 上的 Intel 处理器) 执行。
VV木公子
2021/03/07
11.4K0
iOS逆向之Mach-O文件
二、应用脱壳
iOS端App在上线之前会由苹果商店进行FairPlayDRM数字版权加密保护(简称“加壳”)。要对应用进行分析,就必须先解密(成为“脱壳”),从而得到原始未加密的二进制文件。本节将讨论各种各样的脱壳技术。
Scott_Mr
2022/05/13
1.6K0
二、应用脱壳
iOS端TXLiteAVSDK与其它三方库冲突报错问题
iOS 端在集成腾讯云视频服务客户端音视频SDK时,与开发者自己工程中的第三方库冲突,导致编译报错。
腾讯视频云-Zachary
2019/09/05
3.3K0
iOS端TXLiteAVSDK与其它三方库冲突报错问题
iOS App Store 提交被拒?请收好这份最新 ITMS 错误速查表
在iOS应用分发过程中,超过78%的构建包会在首次提交至App Store Connect时触发ITMS(iTunes Store)系列校验错误。这些由苹果自动化校验系统抛出的错误码(如ITMS-90023、ITMS-90809、ITMS-90713等),实质上是苹果对元数据格式、二进制文件合规性、API调用链完整性等维度的强约束规则集。
移动开发技术
2025/05/22
3660
iOS强化 : 熟悉 Mach-O 文件
Mach-O(Mach Object)是 macOS、iOS、iPadOS 存储程序和库的文件格式。对应系统通过应用二进制接口(application binary interface,缩写为ABI) 来运行该格式的文件。
网罗开发
2021/04/26
1.3K0
iOS强化 : 熟悉 Mach-O 文件
iOS 静态库.a冲突解决
从图中可以知道我去了哪里(前面面试总结文章有人好奇)。 回到正题,以前我是有过专门做SDK的经验,所以像这种sdk报错遇到的不少,如图有价值也很明显的问题点在于:
清墨
2019/07/01
2.2K0
iOS 静态库.a冲突解决
iOS 静态库及动态库开发
阅读文章需要几分钟,伴随早晨的第一缕阳光!开启新的一周,无论你在北京,上海,广州,深圳, 还是其他城市。或许你像我一样在这些城市的地铁,公交,或者它的每个角落!就让我的文章陪着拼搏的你一直前行!依旧来首经典的歌曲!GO!
开发者技术前线
2020/11/23
8100
iOS 静态库及动态库开发
armv6、armv7、armv7s、arm64 与开发静态库(.a)
ARM是微处理器行业的一家知名企业,arm处理器以体积小和高性能的优势在嵌入式设备中广泛使用,它的性能在同等功耗产品中也很出色,几乎所有手机都是使用它的。
全栈程序员站长
2022/09/07
1.4K0
Debian JDK安装及配置
Debian Oracle JDK开发环境配置 ---- Debian是一个非常规范且非常稳定的Linux操作系统,国内使用比较多的Ubutun是他的儿子。一般作为服务器而言相当省心,基本上不用去维护它。 设置编码 nano /etc/default/locale LANG="en_US.UTF-8" LANGUAGE="en_US:en" 如果不支持en_US.UTF-8,需要手动运行dpkg-reconfigure locales选择相应的编码,安装完成之后重启即可。 x86_64架构的Debi
吕海峰
2018/04/03
2.1K0
iOS开发之进阶篇(1)—— 证书、打包上架流程、p12文件
iOS开发相关的证书有很多种,iOS开发证书(iOS App Development)、iOS发布证书(iOS Distribution (App Store and Ad Hoc))、网站推送ID证书(Website Push ID Certificate)、Apple Pay付款处理证书(Apple Pay Payment Processing Certificate)等等。Xcode 11以后,又新增了Apple Development和Apple Distribution,前者是iOS/macOS/tvOS/watchOS各平台开发证书的结合,后者是这些平台的发布证书结合。
iOS Magician
2023/03/22
1.7K0
Xcode 创建.a和framework静态库
最近因为项目中的聊天SDK,需要封装成静态库,所以实践了一下创建静态库的步骤,做下记录。
Haley_Wong
2018/08/22
3.5K0
Xcode 创建.a和framework静态库
推荐阅读
相关推荐
Xcode11打包失敗IPA processing failed
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档