登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
博客
发1篇日志+1圆
记录
发1条记录+2圆币
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
VIP网盘
VIP申请
网盘
联系我们
道具
勋章
任务
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
业界
›
【数据库索引标准结构】B+树原理详解与B树对比优势 ...
【数据库索引标准结构】B+树原理详解与B树对比优势
[ 复制链接 ]
绘纵
前天 10:07
B+ 树是数据库索引最常用、最高效的数据结构之一,它是在 B 树基础上优化而来的。理解其结构和原理,以及为什么它比 B 树更适合数据库,关键在于其设计如何针对磁盘存储和数据库查询模式进行了优化。
一、 B+ 树的结构与原理
核心特征:
多路平衡搜索树:
和 B 树一样,每个节点可以有多个子节点(称为“阶”或“度”,记为 m),这显著降低了树的高度。
所有数据记录存储在叶子节点:
这是与 B 树最本质的区别。
非叶子节点(内部节点)仅存储键(Key)
和指向子节点的指针。这些键充当路由信息,用于在树中导航。
叶子节点包含所有键:
叶子节点不仅存储实际的数据记录(或指向数据记录的指针),还存储了对应的键,并且这些键是按顺序排列的。
叶子节点通过指针串联成有序链表:
所有叶子节点通过双向(或单向)指针连接起来,形成一个按键值排序的有序链表
。这是 B+ 树实现高效范围查询的关键。
树的高度平衡:
插入和删除操作会遵循严格的规则(如节点分裂、合并、借键),保证从根节点到任意叶子节点的路径长度都相同(所有叶子节点都在同一层),确保操作效率的稳定性(O(log n))。
节点填充因子:
通常要求节点(除了根节点)的键数量至少达到 ceil(m/2) - 1,最多为 m - 1(有时定义略有差异,但核心是控制最小填充度)。这保证了空间利用率和树结构的紧凑性。
工作原理:
查找:
从根节点开始。
在当前节点中找到第一个大于或等于目标键的键(通过顺序扫描或二分查找)。
根据该键对应的指针(或小于该键的指针)进入相应的子节点。
重复步骤 2-3,直到到达叶子节点。
在叶子节点中顺序扫描(或二分查找)找到目标键。
如果找到,则获取键关联的数据记录(或指针);如果没找到,则记录不存在。
插入:
按照查找的路径定位到目标键应该插入的叶子节点。
将键(以及对应的数据记录/指针)按顺序插入到该叶子节点。
如果插入后叶子节点键数超过上限 m-1,则进行
节点分裂
:
将该节点分裂成两个节点(通常是均分)。
将分裂后新节点的最小键(或第一个键)
复制
到父节点中(作为新的分隔键),并添加指向新节点的指针。
如果父节点也因此溢出,则递归向上分裂,可能最终导致树的高度增加。
如果根节点分裂,会创建一个新的根节点。
删除:
按照查找的路径定位到包含目标键的叶子节点。
从叶子节点中删除该键及其关联的数据记录/指针。
如果删除后叶子节点的键数低于下限 ceil(m/2) - 1:
尝试借键:
检查相邻的兄弟节点(左或右)。如果某个兄弟节点有富余的键(> ceil(m/2) - 1),则从父节点借一个分隔键下来,并从兄弟节点移一个键(及相应指针)过来,同时更新父节点的分隔键。
节点合并:
如果兄弟节点也没有富余键,则将该节点、一个兄弟节点以及父节点中它们之间的分隔键
合并
成一个新节点(或直接合并到兄弟节点)。删除父节点中的分隔键。
合并操作可能导致父节点下溢,需要递归向上进行借键或合并操作,可能最终导致树的高度降低。
范围查询:
通过查找操作定位到范围起始键所在的叶子节点。
读取该叶子节点上所有满足范围的记录。
沿着叶子节点的链表指针(通常是向右)遍历后续叶子节点,读取并筛选记录,直到遇到超出范围的键。
二、 为什么 B+ 树比 B 树更适合数据库索引?
B+ 树的设计在以下几个方面针对数据库(尤其是基于磁盘的系统)进行了优化,使其相比 B 树具有显著优势:
更高的扇出,更低的树高:
由于
非叶子节点只存储键和指针,不存储数据记录
,所以一个非叶子节点可以容纳更多的键(键比数据记录小得多)。
更高的扇出(一个节点能指向的子节点数)意味着对于相同数量的数据记录,B+ 树的高度通常比 B 树
更低
。
意义:
更低的树高意味着查找、插入、删除操作需要访问的磁盘 I/O 次数
更少
。磁盘 I/O 是数据库操作中最耗时的部分,减少 I/O 是提升性能的关键。即使数据量巨大,B+ 树也能保持较少的层级访问。
更稳定的查询性能(所有查询都到叶子节点):
在 B+ 树中,
任何查询(精确查找、范围查找)都必须遍历到叶子节点才能找到数据
。无论键在树中何处出现(可能在非叶子节点出现多次),数据只在叶子节点。
在 B 树中,数据记录可能存储在任何节点(非叶子或叶子)。这意味着精确查找可能在非叶子节点就找到结果并提前返回。
意义:
B+ 树的查询路径长度总是等于树高,非常稳定和可预测(O(h))。B 树的查询路径长度则可能小于树高(提前找到),但波动性较大。对于数据库系统来说,稳定和可预测的性能非常重要,尤其是在高并发和复杂查询场景下。
无与伦比的范围查询效率:
叶子节点间的有序链表是 B+ 树的核心优势之一。
执行范围查询(如 SELECT * FROM table WHERE key BETWEEN 10 AND 100)时:
B+ 树:找到起始键 (10) 所在的叶子节点后,只需顺序扫描该节点和链表连接的后续叶子节点即可高效获取所有范围内的记录。这最大限度地利用了磁盘的顺序读取特性(远快于随机读取)。
B 树:没有叶子链表。找到起始键后,要获取后续记录,必须不断地回溯到父节点,再定位到下一个子节点(可能在不同的磁盘页),进行中序遍历。这会产生大量的
随机磁盘 I/O
,性能远低于 B+ 树的顺序扫描。
意义:
范围查询是数据库中最常见、最重要的操作之一(如按时间范围筛选、分页查询)。B+ 树对此类查询的优化是革命性的。
更少的空间占用(非叶子节点):
非叶子节点不存储实际数据,只存储键和指针,通常比存储完整数据记录的 B 树非叶子节点
小得多
。
意义:
更多的非叶子节点可以缓存在宝贵的内存中(Buffer Pool),进一步减少磁盘 I/O。
即使需要从磁盘读取非叶子节点,更小的节点意味着一次 I/O 可以读取更多的路由信息(键和指针),间接提升了扇出和降低了树高。
全表扫描更高效:
如果需要对整个表进行扫描(如 SELECT * FROM table,无 WHERE 条件),B+ 树只需遍历叶子节点的链表即可顺序访问所有记录。
B 树进行全表扫描也需要进行树的中序遍历(递归或栈),效率低于顺序扫描链表。
总结对比表
[table][tr]特性B+ 树B 树对数据库的意义[/tr][tr][td]
数据存储位置
[/td][td]
仅在叶子节点
[/td][td]所有节点(叶子 + 非叶子)都可能存储数据[/td][td]B+ 树非叶节点更小,扇出更高[/td][/tr][tr][td]
非叶子节点内容
[/td][td]
仅键 + 指针(路由信息)
[/td][td]键 + 指针 +
可能的数据记录
[/td][td]B+ 树非叶节点更小,扇出更高[/td][/tr][tr][td]
叶子节点连接
[/td][td]
通过指针形成有序链表
[/td][td]无显式链表连接[/td][td]B+ 树范围查询高效(顺序 I/O)[/td][/tr][tr][td]
查找性能稳定性
[/td][td]
稳定
(总是到叶子节点,路径长=树高)[/td][td]
不稳定
(可能中途找到,路径长 ,
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
浏览过的版块
安全
签约作者
程序园优秀签约作者
发帖
绘纵
前天 10:07
关注
0
粉丝关注
14
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
敖可
9984
凶契帽
9990
处匈跑
9990
4
黎瑞芝
9990
5
杭环
9988
6
猷咎
9988
7
鲫疹
9988
8
接快背
9988
9
里豳朝
9988
10
氛疵
9988
查看更多