B树和B+树介绍
前言
维基百科对B树的定义为“在计算机科学中,B树(B-tree)是一种树状数据结构,它能够存储数据、对其进行排序并允许以O(log n)的时间复杂度运行进行查找、顺序读取、插入和删除的数据结构。
B树,概括来说是一个节点可以拥有多于2个子节点的二叉查找树。
与自平衡二叉查找树不同,B-树为系统最优化大块数据的读和写操作。
B-tree算法减少定位记录时所经历的中间过程,从而加快存取速度。普遍运用在数据库和文件系统。
定义
B 树可以看作是对2-3查找树的一种扩展,即他允许每个节点有M-1个子节点。(M为树的层数)
1.根结点至少有两个子女。
2.每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m
3.每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m
4.所有的叶子结点都位于同一层。
5.每个节点中的元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的值域分划。
下图是一个M=4 阶的B树
可以看到B树是2-3树的一种扩展,他允许一个节点有多于2个的元素。
B树的插入及平衡化操作和2-3树很相似,这里就不介绍了。
下面是往B树中依次插入:6 10 4 14 5 11 15 3 2 12 1 7 8 8 6 3 6 21 5 15 15 6 32 23 45 65 7 8 6 5 4
插入演示动画:
B+树是对B树的一种变形树,它与B树的差异在于:
- 有k个子结点的结点必然有k个元素;每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。
- 非叶结点仅具有索引作用,跟记录有关的信息均存放在叶结点中。
- 树的所有叶结点构成一个有序链表,可以按照关键字大小排序,元素次序遍历全部记录。
如图
B+树插入动画
B和B+树的区别在于,B+树的非叶子结点只包含导航信息,不包含实际的值,所有的叶子结点和相连的节点使用链表相连,便于区间查找和遍历。
B+ 树的优点在于:
- 由于B+树在内部节点上不含数据信息,因此在内存页中能够存放更多的key。 数据存放的更加紧密,具有更好的空间局部性。因此访问叶子几点上关联的数据也具有更好的缓存命中率。
- B+树的叶子结点都是相链的,因此对整棵树的便利只需要一次线性遍历叶子结点即可。而且由于数据顺序排列并且相连,所以便于区间查找和搜索。而B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。
B树也有优点,其优点在于
- 由于B树的每一个节点都包含key和value,因此经常访问的元素可能离根节点更近,因此访问也更迅速。
下面是B 树和B+树的区别图:
查询效率
小灰:B+树设计成这样子,究竟有什么好处呢?
小橙:B+树的好处主要体现在查询性能上。我们分别通过单行查询和范围查询进行分析。
单元查询
B+树会自顶向下逐层查找节点,最终找到匹配的叶子节点。比如查询元素3
第一次磁盘IO:
第二次磁盘IO:
第三次磁盘IO:
小灰:好像和B-树查询流程差不多呢!
小橙:看上去确实差不多,但是有两点不同。
1. B+树的中间节点没有数据,所以相同大小磁盘页可以容纳更多的节点元素;这就意味着,数量相同情况下,B+树的结构比B-树更加“矮胖”,因此查询时IO次数更少。
2. B+树查询必须最终查到叶子节点,而B-树只要找到匹配元素即可,无论匹配元素处于中间还是叶子节点;所以B-树查找性能不稳定,可能根节点(最好情况),也可能叶子节点(最坏情况)。而B+树每一次查找都是稳定的。
范围查询
B-树的范围查找过程
自顶向下,查找到范围的下限(3):
中序遍历到元素6:
中序遍历到元素8:
中序遍历到元素9:
中序遍历到元素11,遍历结束:
B+树的范围查找过程
自顶向下,查找到范围的下限(3):
通过链表指针,遍历到元素6, 8:
通过链表指针,遍历到元素9, 11,遍历结束:
由此可见,B+树的要比B-树简单的多。
B+树的优势:
1.单一节点存储更多的元素,使得查询的IO次数更少。
2.所有查询都要查找到叶子节点,查询性能稳定。
3.所有叶子节点形成有序链表,便于范围查询。