尬谈对B+树的我的理解

Today is the first day of the rest of your life. 
今天是你余下人生的第一天。

前言

金三银四,求职者愈来愈活跃,面试官问问题角度愈来愈刁钻。一言不合就问底层实现。你们都知道MySQL索引的实现用到了B+树,本文主要是分享了对B+树的一点我的理解。面试

为何MySQL的索引要用B+树?

众所周知,查找效率比较高的数据结构有不少,呢为何要用B+树呢?先简单分析一下查询效率比较高的几种数据结构。redis

散列表

散列表的查询性能很好,时间复杂度是 O(1)。可是,散列表不能支持按照区间快速查找数据。算法

跳表

跳表是在链表之上加上多层索引构成的。它支持快速地插入、查找、删除数据,时间复杂度是 O(logn)。而且,跳表也支持按照区间快速地查找数据。只须要定位到区间起点值对应在链表中的结点,而后从这个结点开始,顺序遍历链表,直到区间终点对应的结点为止,这期间遍历获得的数据就是知足区间值的数据。mongodb

ps:redis的有序集合就是跳表+散列表构建的

看着好像跳表也能够知足索引的要求。可能由于先有B+树后有的跳表,因此才选的B+?数据库

平衡二叉查找树

平衡二叉查找树查询的性能高,时间复杂度是 O(logn)。并且,对树进行中序遍历,能够获得一个从小到大有序的数据序列,但这仍然不足以支持按照区间快速查找数据。缓存

而且须要考虑一下磁盘的IO,数据索引是存在磁盘上的,当使用索引的时候,会把索引加到内存中去,(内存的访问速度完爆磁盘的访问速度)当数据足够大的时候,把索引完整的加入到内存当中,显然不现实。数据结构

B树

再来看B树,B树相比较平衡二叉查找树,它叉开的比较多,算是多叉平衡查找树。也就是说B树的高度要低,叉要多。若是把二叉查找树比作一我的,那么这我的是又高又有瘦,B树则是又矮又胖,某华真实写照,扎心了。。。性能

ps:树有多高,磁盘就读写多少次。还有mongodb的索引就用到了B。

B+树

B树和B+树实际上是一种树,先由B树到B+树层层递进,逐步分析。
rest

B树和B+树的区别

B树是一个自平衡的多叉查找树。它有如下优势:

  1. 保持键值有序,以顺序遍历
  2. 使用层次化的索引来最小化磁盘读取
  3. 使用不彻底填充的块来加速插入和删除
  4. 经过优雅的遍历算法来保持索引平衡
  5. 经过保证内部节点至少半满来最小化空间浪费。
  6. 能够处理任意数目的插入和删除。

而B+树至关于B树的升级版,相对于B树来讲B+树更充分的利用了节点的空间,让查询速度更加稳定,其速度彻底接近于二分查找(二分查找速度不解释)。B+在基于B树的基础上又有以下优势:

  1. B+树的层级更少:B+树每一个非叶子节点存储的关键字数更多,树的层级更少因此查询数据更快;
  2. B+树查询速度更稳定:B+全部关键字数据地址都存在叶子节点上,因此每次查找的次数都相同因此查询速度要比B树更稳定;
  3. B+树自然具有排序功能:B+树全部的叶子节点数据构成了一个有序链表,在查询大小区间的数据时候更方便,数据紧密性很高,缓存的命中率也会比B树高。
  4. B+树全节点遍历更快:B+树遍历整棵树只须要遍历全部的叶子节点便可,,而不须要像B树同样须要对每一层进行遍历,这有利于数据库作全表扫描。

总结

正由于B+树的这种特性,所以这种数据结构经常使用于文件系统跟数据库索引中。它经过对每一个节点存储个数的扩展,使得对连续的数据可以进行较快的定位和访问,可以有效减小查找时间,提升存储的空间局部性从而减小IO操做。cdn

B+树的特色

  • 每一个节点中子节点的个数不能超过 m,也不能小于 m/2
  •  根节点的子节点个数能够不超过 m/2,这是一个例外
  • m 叉树只存储索引,并不真正存储数据,这个有点儿相似跳表
  •  经过链表将叶子节点串联在一块儿,这样能够方便按区间查找
  •  通常状况,根节点会被存储在内存中,其余节点存储在磁盘中

end


您的点赞和关注是对我最大的支持,谢谢!
相关文章
相关标签/搜索