B树
B-Tree 是一颗多路平衡查找树,广泛用于磁盘访问。
-
当数据量比较庞大的时候,我们需要将其存放在磁盘中,数据以块的形式从磁盘中读取。与内存的访问时间相比,磁盘的访问时间非常长。使用 B 树的的思想是想减少磁盘访问的次数。
-
大多数树操作(搜索、插入、删除、最大值、最小值、..等)需要 O(h) 次磁盘访问,其中 h 是树的高度。B树是一棵"胖"树。通过在 B 树节点中放置最大可能的键,B 树的高度保持在较低水平。从而减少访问磁盘的次数。
下面是一个最小阶数为5的B-Tree的例子。注意,在实际的B-Trees中,最小阶数的值远远大于5。
m 阶B树有以下特性:
- 每个节点最多包含m-1个key,m个子节点。
- 根节点最少包含1个key,2个子节点。
- 非根节点至少包含m/2个key。
- 每个节点中的key都按照从小到大的顺序排列。
- 所有叶子节点都位于同一层。
注意:key (又:关键字),在上图B树的示意图中,画出来的数字就是key,我们在执行查找等操作时,正式依赖key帮我们锁定具体的节点。 同时,在B树中,节点除了包含key之外,还存储了子节点的指针和数据指针(数据索引)
B树节点示意图:
B+树
B+ Tree 是 B Tree 的扩展,它可以更高效的执行插入、删除和搜索操作
-
在 B 树中,内部节点和叶节点中包含key和数据索引。而在 B+ 树中,只有叶子节点上包含数据索引,而内部节点只能存储key。这样的设计是的B+树的内部节点可以存储更多的key,有助于降低树的高度,从而减少磁盘访问次数。
-
B+树的叶节点以单链表的形式链接在一起,使搜索查询更有效率。
从上面我们也可以看出来,B+树中内部节点和叶子节点结构有所不同,下面详细了解一下。
B+树的内部节点结构如下:
- 每个内部节点的结构为:<p 1 , k p 2 .....> 其中 P i 是子节点指针,K i 是 key
- 其中:K 1 < K 2 < ...
- 对于 P1 所指向的子节点,key 值均小于 k1;对于 P2 所指向的子节点,key 值均大于 k1,小于 k2;依次类推。
如图:
B+树的叶子节点结构如下:
- 每个叶节点的结构为: <<k 1 , d>, <k 2 , d>, ....., <k c-1 , d>, P next >
D i 是数据指针(即指向磁盘中键值为 K i 的实际记录或指向包含该记录的磁盘文件块),K i是 key,P next 指向下一个叶子节点。
- 其中:K 1 < K 2 < ...。< K c-1
- 所有叶节点都在同一层。
> 使用P next指针可以像链表一样遍历所有的叶子节点,从而实现对存储在磁盘中的记录的有序访问。
如图:
然后,将内部节点和叶子节点结合到一起。
B+树的示意图:
B树和 B+树的区别
最后总结一下两者的区别:
| B树 | B+树 | |
|---|---|---|
| 1 | 所有内部和叶节点都有数据指针 | 只有叶节点有数据指针 |
| 2 | 由于并非所有键都在叶子上可用,因此搜索通常需要更多时间。 | 所有键都在叶节点,因此搜索更快更准确。 |
| 3 | 树中不存在重复的key | 存在重复的key |
| 4 | 插入删除比较复杂 | 插入删除相对简单 |
| 5 | 叶节点之间不存在指针 | 叶节点之间不存在指针 |
最后:
相比之下,由于B+树的内部节点可以存储更多的key,书的高度也更低,所以磁盘读写代价更小;由于B+树的所有数据指针存储在叶子节点,每次查询都需要从根节点到叶子节点,查询长度相同,所以查询效率也更加稳定;同时,叶子节点指针的存在,这样B+树仅通过叶子指针就可以访问到所有数据,使得在数据扫描、区间查找方面代价更小。综上,B+树更加适用于数据库索引。
水平有限,文中如有错误还望指出。