InnoDB 中 B+ 树索引的分裂

数据库中B+树索引的分裂并不总是从页的中间记录开始,这样可能会导致空间的浪费,例如下面的记录:

1, 2, 3, 4, 5, 6, 7, 8, 9

插入式根据自增顺序进行的,若这时插入10这条记录后需要进行页的分裂操作,那么根据B+树对半分裂的规则,会将记录5作为分裂点记录,分裂后得到下面两个页:

P1: 1, 2, 3, 4
P2: 5, 6, 7, 8, 9, 10

然而由于插入是顺序的,P1这个页中将不再会有记录被插入,从而导致空间的浪费,而P2又会再次分裂。那么如何优化?

InnoDB存储引擎的Page Header有以下几个部分用来保存插入的顺序信息:

  • PAGE_LAST_INSERT:最后插入记录的位置。
  • PAGE_DIRECTION:记录插入的方向。假如新插入的一条记录的主键值比上一条记录的主键值大,我们说这条记录的插入方向是右边,反之则是左边。用来表示最后一条记录插入方向的状态就是PAGE_DIRECTION
  • PAGE_N_DIRECTION:假设连续几次插入新记录的方向都是一致的,InnoDBhi把沿着同一个方向插入记录的条数记下来,这个条数就用PAGE_N_DIRECTION这个状态表示。当然,如果最后一条记录的插入方向改变了的话,这个状态的值会被清零重新统计。

通过这些信息,InnoDB存储引擎可以决定格式向左还是向右进行分裂,同时决定将分裂点记录为哪一个。若插入是随机的,则取页的中间记录作为分裂点的记录,这和之前介绍的相同。若往同一方向进行插入的记录条数为5,并且目前已经定位到的记录(InnoDB引擎插入时,首先需要进行定位,定位到的记录为待插入记录的前一条记录)之后还有3条记录,则分裂点的记录为定位到的记录后的第三条记录,否则分裂点记录就是待插入的记录。(这里的53是固定的,与具体例子无关)

来看一个向右分裂的例子,定位到的记录之后还有3条记录,则分裂点记录如下图所示:

以split record为分裂点记录最终向右分裂得到下图所示的情况:

对于下图的情况,分裂点就为插入记录本身,向右分裂后仅插入记录本身,这在自增插入时是普遍存在的一种情况:

posted @ 2020-06-23 15:35  南小小小小乔  阅读(1574)  评论(2编辑  收藏  举报