之前介绍了B tree,但是在实际应用中,通常会选择B tree的变种即这里的B+ tree作为数据结构,B+ tree究竟在哪些方面优于B tree?
由于《算法导论》中没有对B+ tree的介绍,这里主要参照的是《数据库系统基础 6th》中的内容。
B+ tree和B tree的主要区别在于节点结构与操作。
节点方面:
B+ tree中有两种节点,一个是索引节点,另一个是数据节点。索引节点只包含key和指向子节点的指针,数据节点包含key和指向数据块的指针。(这里如果和B tree比较,B tree的结构和上一篇介绍的略有不同,B tree节点除了有key,还有数据指针,指向数据块,这点在上一篇的9当中有提及)。也就是说在B tree当中所有节点都会指向数据块,但是B+ tree只有数据节点会。
操作方面,这里只说insert。 使用的是回溯的办法,并不是上一片B tree预处理的方式。(在这本书中就是用回溯法的。。。)插入只能在数据节点做,从root遍历至合适的数据节点后,插入,如果满了,就先分裂再插入,但是不同于B tree的是,B tree会把中间的key移至上层,这样之前的节点就不会包含,但是B+ tree则仍会保留。如果回溯过程中索引节点满了,那么仍要分裂,索引节点的分裂与B tree相同,不需要保留副本。
下面上一个例子:
B+ tree插入8,5,1,7,3,12,6
B+ tree的优势:
B+ tree的索引节点只包含了key和子节点指针,少了数据指针,因此对于相同大小的block,参数t可以更大,可以对应更多的数据。我们可以举个例子。
假设block大小为512,数据指针大小为7,树节点指针大小为6,关键字大小为9。
B tree中:设最多可包含p个子节点。
6p+(p -1)*(7+9)<=512,得到p=24。
一般根据规律所得,B tree中的节点一般都是百分之69的饱满度。因此p = 24*0.69 = 16。
节点数 | 关键字数 | 指针数 | |
root | 1 | 15 | 16 |
L1 | 16 | 15*16 | 16*16 |
L2 | 16*16 | 15*16*16 | 16*16*16 |
Leaf | 16*16*16 | 15*16*16*16 |
leaf层的关键字数目就是对应的最大数据块数目,最大为15*16*16*16=61440。
B+ tree中:索引节点最多包含p,数据节点最多pl。
6p+(p - 1)*9 <= 512,得到p=34。明显大于B tree。
6 + pl*(9 + 7) <= 512,得到pl=31。应用0.69得到,p=23,pl=21。
节点数 | 关键字数 | 指针数 | |
root | 1 | 22 | 23 |
L1 | 23 | 22*23 | 23*23 |
L2 | 23*23 | 22*23*23 | 23*23*23 |
Leaf | 23*23*23 | 22*23*23*23 |
最大为22*23*23*23=255507,明显B+ tree的容量大了很多。