B-Tree和B+Tree

简介: 部分内容转载自互联网https://en.wikipedia.org/wiki/B-treehttps://en.wikipedia.org/wiki/B%2B_tree B-Tree 为了描述B-Tree,首先定义一条数据记录为一个二元组[key, data],key为记录的键值,对于不同

部分内容转载自互联网
https://en.wikipedia.org/wiki/B-tree
https://en.wikipedia.org/wiki/B%2B_tree

B-Tree

为了描述B-Tree,首先定义一条数据记录为一个二元组[key, data],key为记录的键值,对于不同数据记录,key是互不相同的;data为数据记录除key外的数据。那么B-Tree是满足下列条件的数据结构:

.1. d为大于1的一个正整数,称为B-Tree的度。

.2. h为一个正整数,称为B-Tree的高度或深度。

.3. 每个非叶子节点由n-1个key和n个指针组成,其中d<=n<=2d。

.4. 每个叶子节点最少包含一个key和两个指针,最多包含2d-1个key和2d个指针,叶节点的指针均为null(因叶子节点是最底层的节点,不需要再指向其他节点) 。

.5. 所有叶节点具有相同的深度,等于树高h。

.6. key和指针互相间隔,节点两端是指针,所以节点中指针比key多一个。

.7. 一个节点中的key从左到右非递减(即升序)排列。

.8. 所有节点组成树结构。

.9. 每个指针要么为null,要么指向另外一个节点。

.10. 如果某个指针在节点node最左边且不为null,则其指向节点的所有key小于v(key1),其中v(key1)为node的第一个key的值。

.11. 如果某个指针在节点node最右边且不为null,则其指向节点的所有key大于v(keym),其中v(keym)为node的最后一个key的值。

.12. 如果某个指针在节点node的左右相邻key分别是keyi和keyi+1且不为null,则其指向节点的所有key小于v(keyi+1)且大于v(keyi)。

图2 是一个d=2的B-Tree示意图。

2

图2

由于B-Tree的特性,在B-Tree中按key检索数据的算法非常直观:
首先从根节点进行二分查找,如果找到则返回对应节点的data,否则对相应区间的指针指向的节点递归进行查找,直到找到节点或找到null指针,前者查找成功,后者查找失败。
B-Tree上查找算法的伪代码如下:

BTree_Search(node, key) {
if(node == null) return null;
foreach(node.key)
{
    if(node.key[i] == key) return node.data[i];
        if(node.key[i] > key) return BTree_Search(point[i]->node);
}
return BTree_Search(point[i+1]->node);
}
data = BTree_Search(root, my_key);

关于B-Tree有一系列有趣的性质,例如一个度为d的B-Tree,设其索引N个key,则其树高h的上限为logd((N+1)/2),检索一个key,其查找节点个数的渐进复杂度为O(logdN)。
从这点可以看出,B-Tree是一个非常有效率的索引数据结构。
另外,由于插入删除新的数据记录会破坏B-Tree的性质,因此在插入删除时,需要对树进行一个分裂、合并、转移等操作以保持B-Tree性质。

B+Tree

B-Tree有许多变种,其中最常见的是B+Tree,例如MySQL就普遍使用B+Tree实现其索引结构。

与B-Tree相比,B+Tree有以下不同点:

.1. 每个节点的指针上限为2d而不是2d+1。(上下矛盾?)

.2. 内节点不存储data,只存储key;叶子节点不存储指针。

图3 是一个简单的B+Tree示意。

3_1_

图3

由于并不是所有节点都具有相同的域,因此B+Tree中叶节点和内节点一般大小不同。
这点与B-Tree不同,虽然B-Tree中不同节点存放的key和指针可能数量不一致,但是每个节点的域和上限是一致的,所以在实现中B-Tree往往对每个节点申请同等大小的空间。

l6UyF
本质差别是B-Tree的每个NODE都记录了data,所以不是每次都要搜叶子节点才能拿到DATA。
B+Tree,只有叶子节点有DATA,因此,每次都要搜到叶子节点取DATA。
但是B+Tree在叶子节点上可以加指向下一个叶子节点的指针,所以范围扫描,B+Tree占优,比如排序。


带有顺序访问指针的B+Tree

一般在数据库系统或文件系统中使用的B+Tree结构都在经典B+Tree的基础上进行了优化,增加了顺序访问指针(称为B* tree)。

4_1_

图4

如图4 所示,在B+Tree的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的B+Tree。做这个优化的目的是为了提高区间访问的性能,例如图4中如果要查询key为从18到49的所有数据记录,当找到18后,只需顺着节点和指针顺序遍历就可以一次性访问到所有数据节点,极大提到了区间查询效率。

B+树的分裂:当一个结点满时,分配一个新的结点,并将原结点中1/2的数据复制到新结点,最后在父结点中增加新结点的指针;
B+树的分裂只影响原结点和父结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针。

B*树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了);
如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针。

所以,B*树分配新结点的概率比B+树要低,空间使用率更高;

PostgreSQL B-Tree 索引

也是一种增强版本,具体算法见
src/backend/access/nbtree/README
主要用了两篇论文中的算法,PostgreSQL的插入性能是非常有保障的.

Lehman and Yao's high-concurrency B-tree management algorithm   
(P. Lehman and S. Yao,Efficient Locking for Concurrent Operations on B-Trees, 
ACM Transactions on Database Systems, Vol 6, No. 4, December 1981, pp 650-670).     

a simplified version of the deletion logic described in Lanin and Shasha   
(V. Lanin and D. Shasha, A Symmetric Concurrent B-Tree Algorithm,  
Proceedings of 1986 Fall Joint Computer Conference, pp 380-389).    

Lehman & Yao Algorithm算法优化
添加了一个右指针(like B+Tree),以及一个upper bound value(解决了分裂的并发问题)。

Compared to a classic B-tree, L&Y adds a right-link pointer to each page,
to the page's right sibling.  It also adds a "high key" to each page, which
is an upper bound on the keys that are allowed on that page.  These two
additions make it possible detect a concurrent page split, which allows the
tree to be searched without holding any read locks (except to keep a single
page from being modified while reading it).

When a search follows a downlink to a child page, it compares the page's
high key with the search key.  If the search key is greater than the high
key, the page must've been split concurrently, and you must follow the
right-link to find the new page containing the key range you're looking
for.  This might need to be repeated, if the page has been split more than
once.

MySQL的请参考
http://tech.it168.com/a2011/0711/1216/000001216087_all.shtml

目录
相关文章
|
存储 关系型数据库 数据库
BTree与B+Tree图文详解
B树与B+树区别
1805 0
BTree与B+Tree图文详解
|
存储 关系型数据库 PostgreSQL
深入浅出PostgreSQL B-Tree索引结构
PostgreSQL 的B-Tree索引页分为几种类别 meta page root page # btpo_flags=2 branch page # btpo_flags=0 leaf page # btpo_flags=1 如果即
15003 0
|
存储 安全 对象存储
如何简单快速搭建自己的云对象存储服务(OSS)
简单来说,其实我们只需要有一台服务器,利用服务器的各种资源,搭配其它厂商开发的软件,就能很轻易拥有自己的云对象存储服务。不需要在阿里云上花钱买什么服务,甚至还能自己给别人提供服务,真的是太爽了。
|
机器学习/深度学习 人工智能 编译器
【AI系统】Auto-Tuning 原理
本文探讨了在多样化硬件平台上部署深度神经网络(DNN)时,传统算子库面临的挑战及解决方案。随着硬件平台的多样化和快速迭代,手动编写高性能算子库变得日益困难。文中介绍了基于TVM的三种自动调优系统——AutoTVM、Ansor和Meta Scheduler,它们通过自动生成高性能算子,有效解决了传统方法的局限性,提高了DNN在不同硬件平台上的执行效率。
395 1
|
Java fastjson Apache
【数据安全】数据脱敏方案总结
【数据安全】数据脱敏方案总结
918 1
|
存储 机器学习/深度学习 编解码
数字图像处理(二) 数字图像处理基础(下)
数字图像处理(二) 数字图像处理基础(下)
522 0
|
存储 缓存 NoSQL
【Java面试题汇总】Redis篇(2023版)
Redis的数据类型、zset底层实现、持久化策略、分布式锁、缓存穿透、击穿、雪崩的区别、双写一致性、主从同步机制、单线程架构、高可用、缓存淘汰策略、Redis事务是否满足ACID、如何排查Redis中的慢查询
【Java面试题汇总】Redis篇(2023版)
|
存储 NoSQL 中间件
【Django+Vue3 线上教育平台项目实战】登录功能模块之短信登录与钉钉三方登录
在当今的数字化时代,用户认证是任何在线服务安全性的基石。本文将简明扼要地介绍登录注册流程中的核心概念:HTTP无状态性、Session、Token与JWT,并详细阐述两种实用登录方式—— 手机号登录验证(借助容联云/云通讯服务) 与钉钉第三方登录。我们将探讨这些概念的基本原理,并深入解析两种登录方式的实现流程,旨在帮助开发者提升用户认证的安全性与便捷性。
【Django+Vue3 线上教育平台项目实战】登录功能模块之短信登录与钉钉三方登录
|
前端开发 数据库 Python
Django自带图形验证码 django-simple-captcha
Django自带图形验证码 django-simple-captcha
215 0
|
SQL 移动开发 Java
“\r\n### Error updating database. ,解决问题的思路在于认真参考给的错误提示,看错误提示,这里我的数据表,没有写primary key 导致的
“\r\n### Error updating database. ,解决问题的思路在于认真参考给的错误提示,看错误提示,这里我的数据表,没有写primary key 导致的