终于有篇看的懂的B树文章了!
索引,相信大多数人已经相当熟悉了,很多人都知道 MySQL 的索引主要以 B+ 树为主,但是要问到为什么用 B+ 树,恐怕很少有人能把前因后果讲述完整。本文就来从头到尾介绍下数据库的索引。

图片来自 Pexels
索引是一种数据结构,用于帮助我们在大量数据中快速定位到我们想要查找的数据。
索引最形象的比喻就是图书的目录了。注意这里的大量,数据量大了索引才显得有意义,如果我想要在 [1,2,3,4] 中找到 4 这个数据,直接对全数据检索也很快,没有必要费力气建索引再去查找。
索引在 MySQL 数据库中分三类:
B+ 树索引
Hash 索引
全文索引
我们今天要介绍的是工作开发中最常接触到的 InnoDB 存储引擎中的 B+ 树索引。
要介绍 B+ 树索引,就不得不提二叉查找树,平衡二叉树和 B 树这三种数据结构。B+ 树就是从他们仨演化来的。
二叉查找树

从图中可以看到,我们为 user 表(用户信息表)建立了一个二叉查找树的索引。
图中的圆为二叉查找树的节点,节点中存储了键(key)和数据(data)。键对应 user 表中的 id,数据对应 user 表中的行数据。
二叉查找树的特点就是任何节点的左子节点的键值都小于当前节点的键值,右子节点的键值都大于当前节点的键值。顶端的节点我们称为根节点,没有子节点的节点我们称之为叶节点。
如果我们需要查找 id=12 的用户信息,利用我们创建的二叉查找树索引,查找流程如下:
将根节点作为当前节点,把 12 与当前节点的键值 10 比较,12 大于 10,接下来我们把当前节点>的右子节点作为当前节点。
继续把 12 和当前节点的键值 13 比较,发现 12 小于 13,把当前节点的左子节点作为当前节点。
把 12 和当前节点的键值 12 对比,12 等于 12,满足条件,我们从当前节点中取出 data,即 id=12,name=xm。
平衡二叉树
上面我们讲解了利用二叉查找树可以快速的找到数据。但是,如果上面的二叉查找树是这样的构造:

下面是平衡二叉树和非平衡二叉树的对比:

B 树
可以想象到二叉树的节点将会非常多,高度也会极其高,我们查找数据时也会进行很多次磁盘 IO,我们查找数据的效率将会极低!

B 树(Balance Tree)即为平衡树的意思,下图即是一棵 B 树:

先找到根节点也就是页 1,判断 28 在键值 17 和 35 之间,那么我们根据页 1 中的指针 p2 找到页 3。
将 28 和页 3 中的键值相比较,28 在 26 和 30 之间,我们根据页 3 中的指针 p2 找到页 8。
将 28 和页 8 中的键值相比较,发现有匹配的键值 28,键值 28 对应的用户信息为(28,bv)。
B+ 树
B+ 树是对 B 树的进一步优化。让我们先来看下 B+ 树的结构图:

聚集索引 VS 非聚集索引
利用聚集索引和非聚集索引查找数据
利用聚集索引查找数据

现在假设我们要查找 id>=18 并且 id<40 的用户数据。对应的 sql 语句为:
select * from user where id>=18 and id < 40
①一般根节点都是常驻内存的,也就是说页 1 已经在内存中了,此时不需要到磁盘中读取数据,直接从内存中读取即可。
从内存中读取到页 1,要查找这个 id>=18 and id <40 或者范围值,我们首先需要找到 id=18 的键值。
从页 1 中我们可以找到键值 18,此时我们需要根据指针 p2,定位到页 3。
②要从页 3 中查找数据,我们就需要拿着 p2 指针去磁盘中进行读取页 3。
从磁盘中读取页 3 后将页 3 放入内存中,然后进行查找,我们可以找到键值 18,然后再拿到页 3 中的指针 p1,定位到页 8。
③同样的页 8 页不在内存中,我们需要再去磁盘中将页 8 读取到内存中。
将页 8 读取到内存中后。因为页中的数据是链表进行连接的,而且键值是按照顺序存放的,此时可以根据二分查找法定位到键值 18。
此时因为已经到数据页了,此时我们已经找到一条满足条件的数据了,就是键值 18 对应的数据。
因为是范围查找,而且此时所有的数据又都存在叶子节点,并且是有序排列的,那么我们就可以对页 8 中的键值依次进行遍历查找并匹配满足条件的数据。
我们可以一直找到键值为 22 的数据,然后页 8 中就没有数据了,此时我们需要拿着页 8 中的 p 指针去读取页 9 中的数据。
④因为页 9 不在内存中,就又会加载页 9 到内存中,并通过和页 8 中一样的方式进行数据的查找,直到将页 12 加载到内存中,发现 41 大于 40,此时不满足条件。那么查找到此终止。
(18,kl),(19,kl),(22,hj),(24,io),(25,vg),(29,jk),(31,jk),(33,rt),(34,ty),(35,yu),(37,rt),(39,rt)。
下面看下具体的查找流程图:

利用非聚集索引查找数据

什么?还看不懂?那我再来解释下吧。首先,这个非聚集索引表示的是用户幸运数字的索引(为什么是幸运数字?一时兴起想起来的:-)),此时表结构是这样的。

如果我们要找到幸运数字为 33 的用户信息,对应的 sql 语句为:
select * from user where luckNum=33

总结
《MySQL 必知必会》
《MySQL 技术内幕 InnoDB 存储引擎第2版》
https://www.cnblogs.com/vianzhang/p/7922426.html
http://blog.codinglabs.org/articles/theory-of-mysql-index.html
作者:安静的boy
编辑:陶家龙、孙淑娟
出处:转载自微信公众号Hollis(ID:hollischuang)

精彩文章推荐:
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号随时掌握互联网精彩
- 1 习近平同马克龙交流互动的经典瞬间 7904246
- 2 公考枪手替考89次敛财千万 7809685
- 3 15岁高中生捐赠南京大屠杀日军罪证 7713460
- 4 2025你的消费习惯“更新”了吗 7616500
- 5 流拍4次的百达翡丽再挂拍 估值4千万 7522450
- 6 一身塑料过冬?聚酯纤维真是塑料瓶吗 7426707
- 7 危险信号!俄数百辆保时捷突然被锁死 7327467
- 8 今日大雪 要做这些事 7237769
- 9 李幼斌20年后重现《亮剑》名场面 7142659
- 10 中疾控流感防治七问七答 7045719







51CTO技术栈
