数据结构 —— B-Tree和B+Tree

B+Tree,B-Tree是棵自平衡的搜索树

【名词解释】空间局部性原理:如果一个存储器的某个位置被访问,那么将它附近的位置也会被访问


一、B-Tree:

B-Tree是专门为外部存储器设计的,如磁盘,它对于读取和写入大量数据有良好的性能。所以一般用于文件系统或者数据库中。MongoDB (索引)使用的是B-树。定义只需要知道B-树允许每个节点有更多的子节点即可。子节点数量一般在上千,具体数量依赖外部存储器的特性。

设计B-Tree结构的目的:

痛点:

传统用来搜索的平衡二叉树有很多,如 AVL 树,红黑树等。这些树存在着一些问题:

  • I/O操作多:这些树在一般情况下查询性能非常好,但当数据非常大的时候它们就无能为力了。因为在数据量巨大的时候,内存就会不够用,因而大部分数据会被存放在磁盘上,只有需要的时候才会将数据读取到内存中。IO的读取时间远远是长于内存的读取,所以数据访问的大部分时间都阻塞在了I/O上。
  • 自平衡受限:平衡二叉树,是通过 旋转 来保持平衡的,而平衡是对于一整棵树来讲的,加载局部数据是无法完成 旋转 的。
  • 其次平衡二叉树的高度相对较大为 log n(底数为2),这样逻辑上很近的节点实际可能非常远,无法很好的利用磁盘预读(局部性原理)

所以这类平衡二叉树在数据库和文件系统上的选择就被 pass 了。

优化:

基于传统二叉树的问题设计了B-Tree,分别从减少I/O,局部自平衡 和 利用磁盘预读方面进行了优化

  • 从“迎合”磁盘的角度上,通过减少I/O的次数来提高程序的性能。为了更快,B-树每次将范围分割为多个区间,区间越多,定位数据越快越精确。多叉的好处非常明显,有效的降低了B-树的高度。因为节点为区间范围,每个节点较大。所以新建节点时,直接申请页大小的空间(磁盘是按 block 分的,一般为 512 Byte。磁盘 IO 一次读取若干个 block,我们称为一页,具体大小和操作系统有关,一般为 4 k,8 k或 16 k),计算机内存分配是按页对齐的,这样就实现了一个节点只需要一次 I/O。
  • 局部自平衡,B-Tree是通过合并和分裂来完成自平衡的。
    分裂:如果有一个节点有 2d 个 key,增加一个后为 2d+1 个 key,不符合上述规则 B-树的每个节点有 d~2d 个 key,大于 2d,则将该节点进行分裂,分裂为两个 d 个 key 的节点并将中值 key 归还给父节点。 
    合并:如果有一个节点有 d 个 key,删除一个后为 d-1 个 key,不符合上述规则 B-树的每个节点有 d~2d 个 key,小于 d,则将该节点进行合并,合并后若满足条件则合并完成,不满足则均分为两个节点。
  • 但是B-Tree未解决利用 磁盘预读功能 的问题。

二、B+Tree:

B+树是B-树的变种,它与B-树的不同之处在于:

  • 在B+树中,key 的副本存储在内部节点,真正的 key 和 data 存储在叶子节点上 。
  • n 个 key 值的节点指针域为 n 而不是 n+1

因为内节点并不存储 data,所以一般B+树的叶节点和内节点大小不同,而B-树的每个节点大小一般是相同的,为一页。

为了增加 区间访问性,一般会对B+树做一些优化。 
如下图带顺序访问的B+树。

B+树可以很好的利用局部性原理,若我们访问节点 key为 50,则 key 为 55、60、62 的节点将来也可能被访问,我们可以利用磁盘预读原理提前将这些数据读入内存,减少了磁盘 IO 的次数。 

三、B+Tree 和 B-Tree的 区别

  • B+树内节点不存储数据,所有 data 存储在叶节点导致查询时间复杂度固定为 log n。而B-树查询时间复杂度不固定,与 key 在树中的位置有关,最好为O(1)
  • B+树叶节点两两相连可大大增加区间访问性,可使用在范围查询等,而B-树每个节点 key 和 data 在一起,则无法区间查找
  • B+树更适合外部存储。由于内节点无 data 域,每个节点能索引的范围更大更精确
    这个很好理解,由于B-树节点内部每个 key 都带着 data 域,而B+树节点只存储 key 的副本,真实的 key 和 data 域都在叶子节点存储。前面说过磁盘是分 block 的,一次磁盘 IO 会读取若干个 block,具体和操作系统有关,那么由于磁盘 IO 数据大小是固定的,在一次 IO 中,单个元素越小,量就越大。这就意味着B+树单次磁盘 IO 的信息量大于B-树,从这点来看B+树相对B-树磁盘 IO 次数少。

参考文章

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值