在MySQL的B+树实现中,非叶子节点通常用双向链表连接,主要是为了提升查询效率,特别是在范围查询或顺序扫描时。具体好处有几个:
-
提高范围查询性能: B+树的叶子节点存储了实际的数据,而非叶子节点主要用来引导搜索路径。如果非叶子节点之间通过双向链表连接,就可以在进行范围查询时直接通过链表快速遍历叶子节点。这避免了再次回到根节点去查找下一个区间,从而提升了性能。
-
顺序访问优化: 由于非叶子节点连接了双向链表,可以快速访问到树的各个部分,特别是在进行顺序遍历时。这对于数据库需要对表进行排序或连续检索时,能显著提高效率。比如,在MySQL的查询优化器中,对于需要顺序扫描的操作,双向链表能够直接顺着链表进行访问,减少了不必要的跳转。
-
避免重复查找路径: 如果只通过树结构查找,查询过程中可能会重复一些路径查找,尤其在进行多次范围查询时,链表连接能够让查询路径更加直观、简单,避免了重复查找。
-
提高并发性能: 在B+树的操作中,非叶子节点通过双向链表连接的设计能让多个查询操作更加独立,减少了节点之间的锁竞争,提升了数据库的并发性能。
总结来说,非叶子节点用双向链表连接,是为了优化范围查询和顺序扫描的效率,减少重复查找路径,提升数据库的整体查询性能。
作者:xinxi
链接:https://www.zhihu.com/question/478187330/answer/2050494617
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
写一个使用场景吧。假如有一个user表,然后它的col1和col2上分别建有索引,于是这两个索引就对应有两个B+树,现在有一个查询语句是 select * from user where col1 > a and col1 < b and col2 > c and col2 <d;,很明显可以使用col1索引或者使用col2索引来进行查询。那到底使用哪个呢?
关键就是要预估一下n和q谁大谁小,假如n较小,那么就使用col1索引。所以需要知道n和q大概是多少。我们知道每个数据页都保存了自己这个页中有多少条数据,所以我们可以通过遍历col1索引中的那m个数据页,把每个页中的条数加起来,这样就知道n的值了;同理可以知道q的值。现在的问题是,假如m和p非常大,成百上千,那么我们就要加载这么多的数据页,很不划算。
实际采取的做法是,只遍历了10个叶子节点,根据这10个节点算出每个节点平均包含多少条数据,然后用这个数据乘以m,就是n的值了。于是现在的问题是怎么知道m是多少?仔细看一下就会发现,m=k,所以怎么知道k的值呢?遍历倒数第二层的那j个页嘛,这个时候倒数第二层的链表是不是就有用了。通过这种方式只需要加载远小于m个数据页,就估出了n的值,同理可以估出q的值,这样就可以决定使用哪个索引去查询啦。
最后,假如j和r还是很大呢?同样的办法,只要10个页,算出平均值,然后找到倒数第三层遍历,用倒数第三层的条数,乘以这个平均值,就得到了k和t。那倒数第三层还是很多呢,继续向上找倒数第四层...