😰在开始前,先澄清一个误区,B减树这个就是通常说的B树,只不过在英文里面写成B-Tree,所以就被读成了B减树。容易产出误区,认为B减树和B树是两个不同的东西。
什么是B-Tree
B-Tree是平衡二叉树的进一步拓展,在二叉树中每个节点至多两个节点,而在B-Tree中每个节点会包含多个子节点,并且每个节点包含多个Key。
对于M路的B-Tree:
- 每个节点的子节点个数为([M/2],M)
- 所有的叶子节点属于同一层(防止树不平衡,导致性能下降)
- 一个包含K个key的节点,应该有K+1个子节点(K个key会划分出K+1个区间)
B-Tree的应用
B-Tree主要用于数据库的索引当中,这个也是B-Tree最初要解决的问题。B-Tree之所以能带来性能的提升是由于磁盘的设计,磁盘的读取是按照扇区来进行读取的,也就是每次的读取都是按照固定大小来进行读取的(比如常见的512B/4KB)。这个和B-Tree的节点正好匹配,每个节点的大小设计为扇区的大小或者其倍数,这样子就可以减少IO的次数,从而提高性能。因为每次IO出来的数据都可以最大限度的获取信息。
B+Tree
在原始的B-Tree中存在几个问题:
- 不支持区间查找、遍历,这个在数据库的搜索中是比较常用的,比如
Select *遍历所有数据。 - 在B-Tree中每个节点的存储都包含Key-Value,查询的性能不固定,有的查询需要查到叶子节点,有的只需查到中间即可。而且由于每个节点占用的空间变大,会导致每个扇区能保存的数据变少,相当于变成了一颗较深的树。
区间查找、遍历
由于在B-Tree中,所有的叶子节点从左到右本来就是按照顺序排列的,所以在B+Tree中就将叶子节点都连接起来形成一个链表。当需要区间查找的时候,只需要通过搜索左区间元素,然后依次遍历就可以得到区间查找的元素。
而遍历只需要,从Head指针开始遍历即可。
查询性能优化
B+Tree的优化:数据只包含在叶子节点,非叶子节点只包含Key。
这个之所以能够优化性能的原因在于:IO的次数会变少。因为每个扇区的大小是固定的,因此如果非叶子节点不包含数据那么每个节点包含的Key就会变多,树的深度就会变小,宽度变大。而查询的次数和树的深度是一致的,因此就可以减少IO的次数,从而提高查询的性能。