B+ 树的简单认识

🚀 优质资源分享 🚀

学习路线指引(点击解锁)知识定位人群定位
🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
💛Python量化交易实战💛入门级手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

B+ 树的概念

基本概念

B+ 树是 B 树的一种变体,从某个程度上看,B+ 树可以认定是 B 树的升级版。

在 B+ 树中,关键字只存储在叶子结点,非叶子结点存储的是叶子结点所存储关键字的部分拷贝,所有的叶子结点也都在相同的高度,叶子结点本身按关键字大小从小到大链接。

因此,相对于 B 树而言,B+ 树更充分地利用了结点的空间,让查询速度更加稳定,其速度完全接近于二分查找。

B+ 树结构

特性

B+ 树拥有 B 树的大部分特性,但也具有独特的、与 B 树不同的特性,不同的地方有以下两点:

  • B+ 树的非叶子结点不直接存储数据的指针,所有数据的指针都存储在叶子结点
  • B+ 树叶子结点存储的数据从小到大有序排列,且相邻叶子结点之间具有链接

与 B 树的区别

与 B 树相比较,B+ 树具有以下特点:

  • B+ 树的非叶子结点不直接存储数据,存储的索引更多,树的层级更少,查询的速度更快
  • B+ 树所有数据的指针都存储在叶子结点,因此每次查找到数据的次数都相同,查询速度更稳定
  • B+ 树所有的叶子结点之间具有链接,构成了一个有序链表,查询范围区间的数据更方便
  • B+ 树遍历所有数据时只需要遍历所有叶子结点即可,相对 B 树遍历更快

为什么使用 B+ 树作为索引结构?

索引的本质是一种用于快速查找记录的数据结构,常见有二叉查找树、平衡二叉树、哈希表、B 树和 B+ 树等索引存储结构。

每一种索引结构都有其对应的应用场景,易用性也是选择的标准之一,这里讨论一下为什么选用 B+ 树作为索引存储结构。

为什么不采用二叉查找树?

二叉查找树索引

使用普通的二叉树查找作为索引结构具有一个致命的问题:当一直插入数据的时候,有可能会退化成链表结构,时间复杂度也会从 O(log⁡n) 退化到 O(n)。

因此,普通的二叉查找树比较适合数据基本没有变动的情况,这样查找效率不会发生较大的变化。

为什么不采用平衡二叉树?

平衡二叉树索引

为了解决普通二叉查找树有可能退化成链表的问题,可以使用自平衡的二叉查找树代替,如 AVL 树、红黑树等。

红黑树常见的一种自平衡二叉查找树,但是也有一个问题:红黑树是一个近似平衡的二叉树,当数据量较大的时候,会出现树层级较大的情况。

当数据量非常大时,索引占用的空间也会非常大,索引还是得存储在磁盘上,如果树的层级较大,则进行磁盘 IO 的次数就会越多,性能就会越差。

因此,红黑树不适合作为存储在磁盘上的索引结构。

为什么不采用哈希表?

哈希表是一个支持快速查找的数据结构,其查找的时间复杂度是 O(1),其也是最常见的索引存储结构之一。

但是哈希表也有其缺点,就是只存储键值对应关系的哈希表不支持范围查询,如果要做范围查询,需要做全量的数据扫描才行。

当然,如果是具有排序功能的哈希表,会非常适合作为存储在内存中的索引结果,如 Java 中的 TreeMap 对象。

为什么不采用 B 树?

使用 B 树可以解决红黑树层级较大的问题,通过一个结点可以存储多个元素,树变得更加矮胖,使得树的层级变得可控。

而且,通过给一个结点存储一页的数据量,最大化地优化操作系统和磁盘的交互,解决了多次磁盘 IO 的问题。

但是对应 B+ 树而言,B 树的层级仍然会比 B+ 树的高,且范围查询没有 B+ 树方便,这是舍弃 B 树而选择 B+ 树的主要原因。

当然,也有使用 B 树作为索引结构的数据库,如 MongoDB 等。

### 计算数据库 B+ 每一层的页数 在理解如何计算B+每层的页数之前,重要的是要认识到每个页面大小通常是固定的,例如16KB[^1]。对于一个典型的B+结构,在MySQL这样的关系型数据库管理系统中,通常情况下两到三层已经足以应对大多数应用场景下的数据量需求[^3]。 #### 基本概念说明 - **页面(Page)**:这是磁盘I/O的基本单位,也是B+节点存储的空间单元。 - **指针(Pointer)**:指向子节点或记录位置的信息片段;每个内部节点包含多个键值和相应的指针。 - **填充因子(Fill Factor)**:决定了一页内实际使用的比例,默认接近满载以减少碎片化并提高性能。 #### 页面容量估算方法 假设有一个非叶子结点能够容纳的最大关键字数目为m,则该节点最多有m+1个孩子(即下一个层次上的页面)。考虑到页面固定大小以及关键字占用字节数等因素的影响: \[ \text{最大关键字数量} = m = (\frac{\text{Page Size}}{\text{Key Length + Pointer Length}})-1\] 这里减去一是因为根节点至少需要两个分支来形成有效的二叉搜索特性。因此,当给定具体的键长度与指针长度时,可以根据上述公式得出单个页面所能承载的关键字上限。 #### 层次扩展规律 随着层数增加,总的可管理的数据项呈几何级数增长。具体来说,如果第i层拥有\( n_i \)个页面,那么其直接下属的(i+1)层理论上可能达到的数量为: \[ n_{(i+1)}=n_i\times(m+1)\] 这意味着即使只有少数几层深,整个索引体系也能够覆盖极其庞大的数据集合而不必担心效率下降问题。 #### 实际案例分析 考虑一个简单的例子,设页面大小为16KB (16,384 bytes),每个键占用了20bytes(包括额外开销),而每次跳转所需的地址信息大约消耗6bytes作为指针。基于此设定,我们可以推导出如下结论: \[ m=(\frac{16384}{20+6})-1≈759 \] 所以最顶层除了根节点外其他各层都几乎可以放置约760个子链接。假设有三个级别的话,第二层会含有近似于 \( 760^2 ≈ 577600\) 个第三层页面,这表明即使是相对较小规模的数据库也能通过不超过三重嵌套实现高效访问控制。 ```sql SELECT COUNT(*) FROM information_schema.INDEX_STATISTICS WHERE TABLE_SCHEMA='your_database'; ``` 这段SQL可以帮助获取关于特定模式下所有表格及其索引统计信息,从而辅助评估现有架构是否合理优化了B+的高度和宽度分布情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

[虚幻私塾】

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值