|
|
# 一、概述
|
|
|
一个m阶的B+树具有如下几个特征:
|
|
|
+ 有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。
|
|
|
+ 所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
|
|
|
+ 所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。
|
|
|
|
|
|
B+树的结构:
|
|
|
![[71cfccb87da28e4cc5b618bcef02a2ac.png]]
|
|
|
|
|
|
上面的这颗树中,得出结论:
|
|
|
根节点元素8是子节点2,5,8 的最大元素,也是叶子节点6,8 的最大元素;
|
|
|
根节点元素15是子节点11,15 的最大元素,也是叶子节点13,15 的最大元素;
|
|
|
根节点的最大元素也就是整个B+树的最大元素,以后无论插入删除多少元素,始终要保持最大的元素在根节点当中。
|
|
|
由于父节点的元素都出现在子节点中,因此所有的叶子节点包含了全部元素信息,并且每一个叶子节点都带有指向下一个节点的指针,形成了一个有序链表。
|
|
|
|
|
|
# 二、卫星数据
|
|
|
指的的是索引元素所指向的数据记录,比如数据库中的某一行,在B-树中,无论中间节点还是叶子节点都带有卫星数据。
|
|
|
|
|
|
B-树中的卫星数据:
|
|
|
![[1fd40497a31465f77367692a09a223c9.png]]
|
|
|
|
|
|
B+树中的卫星数据:
|
|
|
只有叶子节点带有卫星数据,其余中间节点仅仅是索引,没有任何的数据关联。
|
|
|
![[1fd40497a31465f77367692a09a223c9 1.png]]
|
|
|
需要补充的是,在数据库的聚集索引(Clustered Index)中,叶子节点直接包含卫星数据。在非聚集索引(NonClustered Index)中,叶子节点带有指向卫星数据的指针。
|
|
|
|
|
|
# 三、B+树的查询
|
|
|
|
|
|
## 1. 单行查询
|
|
|
比如我们要查找的元素是3:
|
|
|
B+树会自顶向下逐层查找节点,最终找到匹配的叶子节点。
|
|
|
第一次磁盘IO:
|
|
|
![[1fd40497a31465f77367692a09a223c9 2.png]]
|
|
|
|
|
|
第二次磁盘IO:
|
|
|
![[1fd40497a31465f77367692a09a223c9 3.png]]
|
|
|
|
|
|
第三次磁盘IO:
|
|
|
![[1fd40497a31465f77367692a09a223c9 4.png]]
|
|
|
|
|
|
## 2. 范围查询
|
|
|
比如我们要查询3到11的范围数据:
|
|
|
### B-树的范围查询过程:
|
|
|
自顶向下,查找到范围的下限(3):
|
|
|
![[1fd40497a31465f77367692a09a223c9 5.png]]
|
|
|
|
|
|
|
|
|
中序遍历到元素6:
|
|
|
![[1fd40497a31465f77367692a09a223c9 6.png]]
|
|
|
|
|
|
中序遍历到元素8:
|
|
|
![[1fd40497a31465f77367692a09a223c9 7.png]]
|
|
|
|
|
|
中序遍历到元素11,遍历结束:
|
|
|
![[1fd40497a31465f77367692a09a223c9 8.png]]
|
|
|
|
|
|
### **B+树的范围查找过程**
|
|
|
自顶向下,查找到范围的下限(3):
|
|
|
![[1fd40497a31465f77367692a09a223c9 9.png]]
|
|
|
|
|
|
通过链表指针,遍历到元素6, 8:
|
|
|
![[1fd40497a31465f77367692a09a223c9 10.png]]
|
|
|
|
|
|
![[1fd40497a31465f77367692a09a223c9 11.png]]
|
|
|
|
|
|
# 四、总结
|
|
|
B+树比B-树的优势三个:
|
|
|
1. 单一节点存储更多的元素,使得查询的IO次数更少。
|
|
|
2. 所有查询都要查找到叶子节点,查询性能稳定。
|
|
|
3. 所有叶子节点形成有序链表,便于范围查询。 |