联合索引在B+Tree上的存储结构及数据查找方式

最困难的事情就是认识自己!

个人网站,欢迎访问!

前言:

本篇文章主要是阐述下 联合索引 在 B+Tree 上的实际存储结构。

本文主要讲解的内容有:

  • 联合索引在B+树上的存储结构

  • 联合索引的查找方式

  • 为什么会有最左前缀匹配原则

在分享这篇文章之前,我在网上查了关于MySQL联合索引在B+树上的存储结构这个问题,翻阅了很多博客和技术文章,其中有几篇讲述的与事实相悖。具体如下:

很多博客中都是说:联合索引在B+树上的 非叶子节点 中只会存储 联合索引 中的第一个索引字段 的值,联合索引的其余索引字段的值只会出现在 B+树 的 叶子节点 中 。(其实这句话是不对的)

如下图,就是 错误的 联合索引的 B+树 存储结构图:

庆幸的是通过查询发现有一条是来自思否社区的关于【联合索引 在 B+Tree 上的存储结构?】问答,有答主回答了这个问题,并贴出了一篇文章和一张图以及一句简单的描述。 PS:贴出的文章链接已经打不开了

所以在这样的条件下本篇文章就诞生了。

联合索引存储结构:

下面就引用思否社区的这个问答来展开我们今天要讨论的联合索引的存储结构的问题。

来自思否的提问,联合索引的存储结构
(https://segmentfault.com/q/1010000017579884)
有码友回答如下:

联合索引 bcd , 在索引树中的样子如下图 , 在比较的过程中 ,先判断 b 再判断 c 然后是 d :

由于回答只有这么一张图一句话,可能会让大家有点看不懂,所以我们就借助前人的肩膀用这个例子来更加细致的讲探寻一下联合索引在B+树上的存储结构吧。

首先,有一个T1表, 然后表T1有字段a,b,c,d,e,其中a是主键,除e为varchar其余为int类型,并创建了一个联合索引idx_t1_bcd(b,c,d),然后b、c、d三列作为联合索引,在B+树上的结构正如上图所示。联合索引的所有索引列都出现在索引数上,并依次比较三列的大小。上图树高只有两层不容易理解,下面是假设的表数据以及我对其联合索引在B+树上的结构图的改进。 PS:基于InnoDB存储引擎。

index(b、c、d)联合索引在B+树上的结构图如下:

T1表中的数据如下图:( 上图 B+树 中的数据就来自下图

通过这俩图我们心里对联合索引在B+树上的存储结构就有了个大概的认识。下面用我的语言为大家解释一下吧。

我们先看T1表,他的主键暂且我们将它设为整型自增的 ,InnoDB会使用主键索引在B+树维护索引和数据文件,然后我们创建了一个联合索引(b,c,d)也会生成一个索引树,同样是B+树的结构,只不过它的 data部分 存储的是联合索引所在行记录的主键值 (上图叶子节点紫色背景部分) 。为什么是 主键值,而不是 整个行记录呢? 因为这个 联合索引 是个 非聚簇索引

好了大致情况都介绍完了。下面我们结合这俩图来解释一下。

对于联合索引来说只不过比单值索引多了几列,而这些索引列全都出现在索引树上。对于联合索引,存储引擎会首先根据第一个索引列排序,如上图我们可以单看第一个索引列,如,1 1 5 12 13…它是单调递增的;如果第一列相等则再根据第二列排序,依次类推就构成了上图的索引树,上图中的1 1 4 ,1 1 5以及13 12 4, 13 16 1, 13 16 5就可以说明这种情况。

联合索引具体查找步骤:

当我们的SQL语言可以应用到索引的时候,比如 select * from T1 where b = 12 and c = 14 and d = 3 ;也就是T1表中a列为4的这条记录。

查找步骤具体如下:

  1. 存储引擎首先从根节点(一般常驻内存)开始查找,第一个索引的第一个索引列为1,12大于1,第二个索引的第一个索引列为56,12小于56,于是从这俩索引的中间读到下一个节点的磁盘文件地址(此处实际上是存在一个指针的,指向的是下一个节点的磁盘位置)。
  2. 进行一次磁盘IO,将此节点值加载后内存中,然后根据第一步一样进行判断,发现 数据都是匹配的,然后根据指针将此联合索引值所在的叶子节点也从磁盘中加载后内存,此时又发生了一次磁盘IO,最终根据叶子节点中索引值关联的 主键值
  3. 根据主键值 回表 去主键索引树(聚簇索引)中查询具体的行记录。

联合索引的最左前缀原则:

之所以会有最左前缀匹配原则和联合索引的索引构建方式及存储结构是有关系的。

首先我们创建的idx_t1_bcd(b,c,d)索引,相当于创建了(b)、(b、c)(b、c、d)三个索引,看完下面你就知道为什么相当于创建了三个索引。

我们看,联合索引是首先使用多列索引的第一列构建的索引树,用上面idx_t1_bcd(b,c,d)的例子就是优先使用b列构建,当b列值相等时再以c列排序,若c列的值也相等则以d列排序。我们可以取出索引树的叶子节点看一下。

索引的第一列也就是b列可以说是从左到右单调递增的,但我们看c列和d列并没有这个特性,它们只能在b列值相等的情况下这个小范围内递增,如第一叶子节点的第1、2个元素和第二个叶子节点的后三个元素。

由于联合索引是上述那样的索引构建方式及存储结构,所以联合索引只能从多列索引的第一列开始查找。所以如果你的查找条件不包含b列如(c,d)、(c)、(d)是无法应用缓存的,以及跨列也是无法完全用到索引如(b,d),只会用到b列索引。

这就像我们的电话本一样,有名和姓以及电话,名和姓就是联合索引。在姓可以以姓的首字母排序,姓的首字母相同的情况下,再以名的首字母排序。

如:

M
    毛 不易   178********
    马 化腾   183********
    马 云     188********
Z
    张 杰     189********
    张 靓颖   138********
    张 艺兴   176********  

我们知道名和姓是很快就能够从姓的首字母索引定位到姓,然后定位到名,进而找到电话号码,因为所有的姓从上到下按照既定的规则(首字母排序)是有序的,而名是在姓的首字母一定的条件下也是按照名的首字母排序的,但是整体来看,所有的名放在一起是无序的,所以如果只知道名查找起来就比较慢,因为无法用已排好的结构快速查找。

到这里大家是否明白了为啥会有最左前缀匹配原则了吧。

实践:

如下列举一些SQL的索引使用情况:

select * from T1 where b = 12 and c = 14 and d = 3;-- 全值索引匹配 三列都用到
select * from T1 where b = 12 and c = 14 and e = 'xml';-- 应用到两列索引
select * from T1 where b = 12 and e = 'xml';-- 应用到一列索引
select * from T1 where b = 12  and c >= 14 and e = 'xml';-- 应用到一列索引及索引条件下推优化
select * from T1 where b = 12  and d = 3;-- 应用到一列索引  因为不能跨列使用索引 没有c列 连不上
select * from T1 where c = 14  and d = 3;-- 无法应用索引,违背最左匹配原则

后记:

到这里MySQL索引的联合索引的存储结构及查找方式就讲完了,本人能力有限,也是站着前人的肩膀上创作的此文,因为看到搜索引擎的搜索结果前几个技术文章中有存在讲述不清或讲述有误的地方,所以自己才总结出这篇文章分享给大家,如有不对的地方一定要指正哦,谢谢了。

通过本文了解到了联合索引的存储结构及查找方式,那在项目中该怎么创建索引呢?请参考此文:项目中该如何创建索引?

不要忘记留下你学习的足迹 [点赞 + 收藏 + 评论]嘿嘿ヾ

一切看文章不点赞都是“耍流氓”,嘿嘿ヾ(◍°∇°◍)ノ゙!开个玩笑,动一动你的小手,点赞就完事了,你每个人出一份力量(点赞 + 评论)就会让更多的学习者加入进来!非常感谢! ̄ω ̄=

个人原创Java技术文公众号,欢迎大家关注;关注后如果 不香 ,来捶我啊!嘿嘿。。。。。。

  • 91
    点赞
  • 134
    收藏
    觉得还不错? 一键收藏
  • 38
    评论
### 回答1: B树(B-tree)是一种自平衡的搜索树数据结构,适用于存储大量有序的数据,常用于数据库和文件系统中。B树可以高效地支持插入、删除和查找操作。 B树的结构特点如下: 1. 每个节点可以存储多个关键字,且关键字按照升序排列。 2. 所有叶子节点在同一层上,且通过指针连接起来。 3. 除根节点外,每个节点的关键字个数满足:[ceil(m/2)-1, m-1],其中m为节点的最大关键字个数。 4. 每个非叶子节点的关键字个数比其子节点的个数少1。 B树的操作如下: 1. 查找:从根节点开始,在每个节点中查找目标关键字,直到找到或到达叶子节点。 2. 插入:首先查找到插入位置对应的叶子节点,如果该叶子节点未满,则直接插入。如果该叶子节点已满,则进行节点分裂操作,将中间关键字上移,并为其父节点创建一个新的子节点。 3. 删除:首先查找到要删除的目标关键字位置对应的叶子节点。如果该叶子节点中存在该关键字,则直接删除。如果该叶子节点不存在该关键字,则进行节点合并操作,将其兄弟节点中的一个关键字拿来替换,并更新相关指针。 4. 节点合并和分裂:当一个节点满时需要进行节点分裂操作,将中间关键字上传并创建新的节点。当一个节点的关键字个数小于[ceil(m/2)-1]时需要进行节点合并操作,将其与相邻节点合并。 B树相较于二叉搜索树(BST)的优势在于: 1. 减少了平衡操作的次数,提高了插入、删除和查找操作的效率。 2. 可以存储更多的关键字,减少了内存开销。 3. 更适用于在磁盘上存储数据,因为B树每个节点可以存储更多的关键字,减少了磁盘IO次数。 总之,B树是一种高效的自平衡搜索树数据结构,适用于存储大量有序数据,特别是在数据库和文件系统中的应用广泛。 ### 回答2: B树(B-tree)是一种自平衡的搜索树数据结构,也是一种多路搜索树。它能够在 O(log N) 时间复杂度内进行搜索、插入和删除操作,具有高效的查找性能。B树常用于文件系统以及数据库管理系统中,用于存储和管理大量的有序数据。 B树的特点在于: 1. 每个节点可以拥有多个子节点,称为多路搜索树。通过拥有更多的子节点,B树能够存储更多的数据,减少树的高度。 2. 节点内的数据按照升序排列,并且节点的子节点的值范围也有序,可以通过二分查找进行快速定位。 3. 所有叶子节点都位于相同的层级上,没有指向其他节点的指针,提高了访问叶子节点的效率。 4. B树的平衡性是通过定义一个最小度数来保证。最小度数 t 确定了一个节点最少需要拥有 t-1 个键和 t 个子节点。 B树的插入和删除操作: 1. 插入操作:首先进行搜索找到插入位置,如果节点不满,直接将键插入到节点中;若节点满了,则需要进行节点分裂操作,将中间键上升到父节点中,同时分裂成两个节点。 2. 删除操作:首先进行搜索找到要删除的键。如果要删除的键在叶子节点上,直接删除;若在非叶子节点上,则需要查找其后继节点或前驱节点来替换删除的键。若删除后节点的关键字数小于最小度数,则进行合并或者重新分配。 总结起来,B树通过多路搜索、平衡性和节点分裂合并操作,提供了高效的数据存储与搜索方法。它在处理大量有序数据时具有很好的性能,并且被广泛应用于许多存储和数据库系统中。 ### 回答3: B-树(B-Tree)是一种平衡的多叉树,用于存储和管理大量的数据元素。它是一种自平衡的数据结构,可以高效地支持插入、删除和查找操作。B-树在数据库领域应用广泛,尤其适用于文件系统和数据库索引的实现。 B-树的特点包括: 1. 多叉:每个节点可以有多个子节点,相比于二叉树,B-树的宽度更大。 2. 自平衡:B-树通过保持其高度相对较小而保持平衡。在插入和删除操作中,B-树会通过旋转和分裂节点等操作来维持平衡。 3. 顺序访问:B-树节点中的数据元素是按照顺序排列的,使得范围查询操作更高效。 4. 多层级:B-树是多层级的,更适合大规模数据的存储和查询。 B-树的应用场景包括: 1. 数据库索引:B-树被广泛用于实现数据库的索引结构。它可以加速数据库中数据查找操作。 2. 文件系统:B-树也可以用于文件系统中的文件索引,提供高效的文件访问能力。 3. 磁盘存储:由于B-树可以减少磁盘I/O操作的次数,因此在大规模存储中应用广泛。 4. 并发控制:在多用户环境下,B-树可以有效地进行并发控制,提供高性能的数据访问。 总之,B-树是一种高效、自平衡的多叉树数据结构。它通过调整节点的旋转和分裂,保持树的平衡性,并且提供高效的数据存储和访问能力。在大规模的数据库和文件系统中,B-树是一种非常重要的数据结构,它可以提高数据的查询和访问效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 38
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值