腾讯、阿里面试题: 了解B+树吗?
由于MySQL
的索引结构是B+树,所以B+树是大厂的高频面试题,想理解B+树,最好先理解B树,下面详细介绍B树、B+树
B树
-
B树的概念
B树又称为B-树,是一种平衡多路查找树,描述B树,一般需要指定其阶数 M M M,阶数指的是一个节点包含的子节点最大数量。当 M M M取2的时候,就是常见的二叉树
其有如下性质:
- 每个节点最多有 M − 1 M-1 M−1个关键字
- 除根节点外,其余的节点至少有 c e i l ( M / 2 ) − 1 ceil(M/2)-1 ceil(M/2)−1个关键字( c e i l ceil ceil向上取整函数)
- 每个结点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它
- 所有叶子结点都位于同一层,或者说根结点到每个叶子结点的长度都相同。
-
B树的插入操作
如下描述是B树的插入算法,相对来说比较简单
-
找到关键字的插入位置,一定是叶节点位置,进行插入操作
-
插入后,如果当前节点的关键字数量小于等于 M − 1 M-1 M−1,则结束,否则执行步骤3
-
进行分裂操作,当前节点按中间关键字分裂成三部分,中间关键字插入到父节点中,
左边部分,成为中间关键字的左节点,右边部分成为中间关键字的右节点,然后
当前节点指向父节点,转到2,执行递归操作。
下面是一个5阶B树的分裂过程,上面图是分裂前,下面图是分裂后
-
-
B树的构建过程
下面以构建一个5阶树,介绍B树的构建过程。
-
依次插入关键字3,5, 2, 6
-
插入4的时候,由于当前节点关键字数量等于M(5),需要进行分裂操作
-
依次插入关键字1,8,7,9插入
9
的时候又进行了分裂 -
依次插入关键字10,11,12插入
12
的时候又进行了分裂过程 -
插入关键字13,14,15,16,17,中间插入15的时候进行了分裂操作
-
最后插入18,进行了两次分裂操作
其实插入的过程会发现,顺序插入空间效率最差,比如[11,12]节点,就插入不了任何元素.
-
-
B树的删除过程
B树的删除算法较为复杂,下面首先介绍算法,之后结合实例,阐述
- 查找关键字,如果不存在,结束,否则进入步骤2.
- 如果关键字处于叶节点,直接删除。如果关键字处于非叶子节点,则用其前继关键字(前继关键字一定位于叶节点)覆盖要删除的关键字,之后删除后继关键字,将当前节点指向包含后继关键字的节点。以上两种情况,均最后转入步骤3
- 如果当前节点关键字数量大于等于 c e i l ( M / 2 ) − 1 ceil(M/2)-1 ceil(M/2)−1,则结束,否则转入4
- 如果兄弟节点(不论左兄弟,还是右兄弟),关键字数量大于 c e i l ( M / 2 ) − 1 ceil(M/2)-1 ceil(M/2)−1,则父节点中对应的关键字下移到当前节点,兄弟节点对应的关键字上移到父节点,结束。若无兄弟节点关键字数量大于 c e i l ( M / 2 ) − 1 ceil(M/2)-1 ceil(M/2)−1,则转入步骤5
- 合并操作,将父结点中关键字下移与当前结点及它的兄弟结点中的官架子合并,形成一个新的结点。原父结点中的key的两个孩子指针就变成了一个孩子指针,指向这个新结点。当前节点指向父节点,重复2,进行递归操作。
下面是一个5阶数的删除过程实例
原B树如下图所示
-
B树的优缺点
B树主要的优点是相对于二叉树,每个节点包括更多的关键字,所以其树高相对较低,查找效率很高.
B+树
-
B+树的概念
- B+树包含两种节点,一种是非叶子节点(索引节点),一种是叶子节点。
- B+树与B树,最大的不同是B+树的非叶子节点不保存数据,只用于索引,所有数据都保存在叶子节点
- 非叶子节点最多有 M − 1 M-1 M−1个关键字,阶数 M M M同时限制了叶子结点最多存储 M − 1 M-1 M−1个记录。
- 索引节点中的key都按照从小到大的顺序排列,对于内部结点中的一个key,左树中的所有key都小于它,右子树中的key都大于等于它。叶子结点中的记录也按照key的大小排列。
- 每个叶子节点都存有相邻叶子节点的指针,叶子节点本身依关键字的大小自小而大顺序链接(范围查找特性)
-
B+树插入
-
B+树插入算法
-
通过查找,确定关键字的插入位置,插入位置一定位于叶节点,插入后,如果当前
节点关键字数量小于等于 M − 1 M-1 M−1,算法结束,否则转入步骤2.
-
分裂过程,将当前节点,分为左右两个叶子节点,左叶子节点包含前 M / 2 M/2 M/2个记录,
右叶子节点包含剩余记录,并且将第 M / 2 + 1 M/2+1 M/2+1个记录的关键字上移到父节点。当前节点指针指向父节点,然后执行步骤3.(父节点一定是索引节点)
-
如果当前节点的关键字数量小于 M M M,则插入结束,否则,将当前索引节点以中间关键字为中心分裂成两个索引节点,左索引节点和右索引节点,并将中间关键字上移到父节点中。并且其左节点为上面提到的
左索引节点
,其右节点为右索引节点
。将当前节点指针指向父节点,重复步骤3
-
-
B+树插入实例
如下是一个5阶B+数的构造过程
-
依次插入1、5、9、13
-
插入17的时候,发生分裂过程
-
依次插入2、3、4,插入4的时候,发生分裂过程
-
依次插入10,11,插入11的时候,发生分裂过程
-
插入12,14,插入14的时候,发生分裂过程
-
插入15,16,插入16的时候,发生两次分裂过程,依次在叶节点,和索引节点
-
-
-
B+树删除
-
B+树删除算法
-
找到目标关键字所在的叶节点位置,进行删除,若删除后,当前节点关键字数量大于
等于 c e i l ( M / 2 ) − 1 ceil(M/2)-1 ceil(M/2)−1,结束,否则转到步骤2
-
若兄弟节点有富余(大于 c e i l ( M / 2 ) − 1 ceil(M /2 )-1 ceil(M/2)−1),向兄弟借一个记录,同时用借到的key替换父节点中对应的关键字,结束。否则转到步骤3
-
若兄弟节点没有富余,则当前节点和兄弟节点合并成一个新的节点,删除父节点的关键字,新节点指向父节点相应的位置。执行步骤4
-
若索引节点的关键字个数大于等于 c e i l ( M / 2 ) − 1 ceil(M/2)-1 ceil(M/2)−1,则结束,否则执行5
-
若兄弟结点有富余,父结点key下移,兄弟结点key上移,删除结束。否则执行第6步
-
当前结点和兄弟结点及父结点下移key合并成一个新的结点。将当前结点指向父结点,重复第4步
4,5,6步类似B树的删除过程
-
-
B+树删除算法实例
原来的一个5阶树
-
-
B+树的优点
1、B+树的层级更少:相较于B树B+每个非叶子节点存储的关键字数更多,树的层级更少所以查询数据更快;
2、B+树查询速度更稳定:B+所有关键字数据地址都存在叶子节点上,所以每次查找的次数都相同所以查询速度要比B树更稳定;
3、B+树天然具备排序功能:B+树所有的叶子节点数据构成了一个有序链表,在查询大小区间的数据时候更方便,数据紧密性很高,缓存的命中率也会比B树高。
4、B+树全节点遍历更快:B+树遍历整棵树只需要遍历所有的叶子节点即可,,而不需要像B树一样需要对每一层进行遍历,这有利于数据库做全表扫描。
B树相对于B+树的优点是,如果经常访问的数据离根节点很近,而B树的非叶子节点本身存有关键字其数据的地址,所以这种数据检索的时候会要比B+树快。