这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战
前言
面试造火箭,工作拧螺丝,这里是造火箭系列第四期,今天我们来造的火箭主题是 —— B+ Tree,同样的,这个问题也是经典的面试猛如虎,工作没卵用系列,虽然我们工作的时候并不需要去了解那么多这些相关的问题,但是怎奈何面试的时候要用啊,所有,我们也来聊聊这个问题。
需求分析
我们知道对于索引来说,最重要的就是优化查询的过程,而对于查找来说,主要可以分为精确查找和范围查找两个类别,但其实,如果对于一个有序的数组来说,直接进行二分查找就非常的快了,并不需要去使用索引。
但是却会有一个问题,那就是在插入数据的时候,性能会非常的差,因为要保证数组的有序,所以时间复杂度要去到O(n)级别。
还有一个问题,那就是如果数组的大小超过了内存的大小,那么就需要考虑怎么把一部分数据被放到磁盘中,同时对于一个有序数组的增删改的性能都是非常的差的。
二分搜索树
通过上面的问题,能想到的第一个版解决方案,那就是使用二分搜索树来替代所用的有序数组,通过这样的替换,原来增删改的O(n)的复杂度就变成了O(logn),同时查询的时候的复杂度也变成了O(logn)。
弊端
但是二分搜索树同样存在一个弊端,那就是在进行范围查询的时候非常的麻烦,因为他需要不断的从根节点开始向下遍历,所以会很慢。
解决方案
为了解决这个问题,我们对树的结构进行第二次的改造,把所有的数据都存在于根节点处,然后根节点之间通过指针相连,也就是对于树的根节点,相当于是一个双向链表。
这样的方式就解决了范围查询的一个问题,在范围查询或者是精确查询的时候,效率都还过得去。
多叉树
对于二分搜索树来说,其查询的效率是跟树的高度有关的,假设我们有2000万的数据规模,那么就大概需要有25BST的一个树高的树才可以装下整个数据,那么在查询的时候,需要进行25次的I/O操作。
我们对它进一步的优化步骤,就是把树变得更加的矮胖,也就是把二分搜索树,变成一个多叉搜索树。
这个多叉搜索树,其实也就是B+Tree,它的一个主要特点就是,所有数据只存在于叶子节点,同时叶子节点之间通过双端链表连接起来,从而优化了范围查询的问题。
B-Tree和B+Tree的区别
B-Tree相对于B+Tree来说,最大的区别就是他的数据是存在于每一个节点的,并不像B+Tree那样都是存在于叶子节点。
而对于这两种树的主要区别就是在进行范围查询的时候,因为B-Tree节点间是通过父子关系连接的,所以如果使用范围查询的时候,就必须通过回表的方式来查询。
而B+Tree因为有了双向链表的关系,所以不会有这个问题。
最后
面试造火箭系列这期就到这里,让我们下期再见。