InnoDB的B+索引树的注意事项

1. 根页面位置万年不变

我们介绍B+树索引的时候,为了方便大家理解,先把存储用户记录的叶子节点都画出来,然后接着画存储目录项记录的内节点,实际上B+树的形成过程是这样的。

  1. 每当为某个表创建一个B+树索引(聚集索引不是人为创建的,默认就有)的时候,都会为这个索引创建一个根节点页面。最开始表中没有数据的时候,每个B+树索引对应的根节点中既没有数据,也没有目录项记录
  2. 随后向表中插入数据时,先把用户记录存储到这个根节点中
  3. 当根节点中的可用空间用完时继续插入,此时会将根节点中的所有记录复制到一个新分配的页,比如页a中,然后对这个新页进行 页分裂的操作,得到另一个新页,比如页b。这时新插入的记录根据键值(也就是聚簇索引中的主键值,二级索引中对应的索引列的值)的大小就会被分配到页a或者页b中,而根节点便升级为存储目录项记录的页)

这个过程特别注意的是:一个B+树索引的根节点自诞生之日起,便不会再移动。这样只要我们对某个表建立一个索引,那么它的根节点的页号便会记录到某个地方,然后凡是InnoDB存储引擎需要用到这个索引的时候,都会从那个固定的地方取出根节点的页号,从而来访问这个索引 

2.内节点中目录项记录的唯一性

我们知道B+树索引的内节点中目录项记录的内容是索引列+页号的搭配,但是这个搭配对于二级索引来说有点儿不严谨。还拿index_demo表为例,假设这个表中的数据是这样的

如果二级索引中目录项记录的内容只是索引列+页号的搭配的话,那么为c2列建立索引后的B+树应该长这样

 如果我们想新插入一条记录,其中c1、c2、c3的值分别是:9、1、‘c’,那么在修改这个为c2列建立的二级索引对应的B+树时便碰到了个大问题:由于页3中存储的目录项记录是由c2列+页号构成的,页3中的两条目录项对应的c2列的值都是1,而我们新插入的这条记录的c2列的值也是1,那我们这条新插入的值到底应该放到页4中,还是应该放到页5中。答案是:对不起,懵逼了

为了让新插入记录能找到自己在那个页里,我们需要保证在B+树的同一层内节点的目录项记录除页号这个字段以外是唯一的,所以对于二级索引的内节点的目录项记录的内容实际上市由三个部门组成的。

  • 索引列的值
  • 主键值
  • 页号

也就是是我们把主键值也添加到二级索引内节点中的目录项记录了,这样就能保证B+树每一层节点中各条目录项除页号这个字段外是唯一的,所以我们为c2列建立二级索引后的示意图实际上应该是这样子的 

 这样我们再插入记录(9,1,‘c’时)由于页3中存储的目录项记录是由c2列+主键+页号的值构成的,可以先把新纪录的c2列的值和页3中各目录项记录的c2列的值作比较,如果c2列的值相同的话,可以接着比较主键值,因为B+树同一层中不同目录项记录的c2列+主键的值肯定是不一样的,所以最后肯定能定位唯一的一条目录项记录,在本例中最后确定新纪录应该被插入到页5中

3. 一个页面最少存储2条记录

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值