目前大多数数据库系统及文件系统都采用 B-Tree 或其变种 B+Tree 作为索引结构。B+ 树中的 B (balance)代表平衡,而不是二叉。B+ 树是从最早的平衡二叉树演化而来的。B+ 树是由二叉查找树、平衡二叉树(AVLTree)和平衡多路查找树(B-Tree)逐步优化而来。

  • 二叉查找树:左子树的键值小于根的键值,右子树的键值大于根的键值。
  • AVL 树:平衡二叉树(AVL 树)在符合二叉查找树的条件下,还满足任何节点的两个子树的高度最大差为 1,但不是红黑树。
  • 平衡多路查找树(B-Tree):为磁盘等外存储设备设计的一种平衡查找树。

那么纠结该如何选型呢?

索引的标准:IO渐进复杂度,说白了就是推演过程(每个节点都是1次IO),B+树是为磁盘及其他存储辅助设备而设计一种平衡查找树(不是二叉树),所有记录的节点按大小顺序存放在同一层的叶节点中,各叶节点用指针进行连接。

InnoDB 存储引擎使用页作为数据读取单位,页是其磁盘管理的最小单位,默认 page 大小是 16k。系统的一个磁盘块的存储空间往往没有这么大,因此 InnoDB 每次申请磁盘空间时都会是若干地址连续磁盘块来达到页的大小 16KB。在查询数据时如果一个页中的每条数据都能助于定位数据记录的位置,这将会减少磁盘 I/O 的次数,提高查询效率。

3.1 B-Tree

B-树是一种多路自平衡的搜索树 它类似普通的平衡二叉树,不同的一点是B-树允许每个节点有更多的子节点。B-Tree 相对于 AVLTree 缩减了节点个数,使每次磁盘 I/O 取到内存的数据都发挥了作用,从而提高了查询效率。

注:B-Tree就是我们常说的B树,一定不要读成B减树,否则就很丢人了

那么m阶 B-Tree 是满足下列条件的数据结构:

  1. 所有键值分布在整颗树中
  2. 搜索有可能在非叶子结点结束,在关键字全集内做一次查找,性能逼近二分查找
  3. 每个节点最多拥有m个子树
  4. 根节点至少有2个子树
  5. 分支节点至少拥有m/2颗子树(除根节点和叶子节点外都是分支节点)
  6. 所有叶子节点都在同一层、每个节点最多可以有m-1个key,并且以升序排列

每个节点占用一个磁盘块,一个节点上有两个升序排序的关键字和三个指向子树根节点的指针,指针存储的是子节点所在磁盘块的地址。两个关键词划分成的三个范围域对应三个指针指向的子树的数据的范围域。以根节点为例,关键字为 17 和 35,P1 指针指向的子树的数据范围为小于 17,P2 指针指向的子树的数据范围为 17~35,P3 指针指向的子树的数据范围为大于 35。

模拟查找关键字 29 的过程:

  1. 根据根节点找到磁盘块 1,读入内存。【磁盘 I/O 操作第 1 次】
  2. 比较关键字 29 在区间(17,35),找到磁盘块 1 的指针 P2。
  3. 根据 P2 指针找到磁盘块 3,读入内存。【磁盘 I/O 操作第 2 次】
  4. 比较关键字 29 在区间(26,30),找到磁盘块 3 的指针 P2。
  5. 根据 P2 指针找到磁盘块 8,读入内存。【磁盘 I/O 操作第 3 次】
  6. 在磁盘块 8 中的关键字列表中找到关键字 29。

分析上面过程,发现需要 3 次磁盘 I/O 操作,和 3 次内存查找操作。由于内存中的关键字是一个有序表结构,可以利用二分法查找提高效率。而 3 次磁盘 I/O 操作是影响整个 B-Tree 查找效率的决定因素。

但同时B-Tree也存在问题:

  • 每个节点中有key,也有data,而每一个页的存储空间是有限的,如果data数据较大时将会导致每个节点(即一个页)能存储的 key 的数量很小。
  • 当存储的数据量很大时同样会导致 B-Tree 的深度较大,增大查询时的磁盘 I/O 次数,进而影响查询效率

3.2 B+Tree

B+Tree 是在 B-Tree 基础上的一种优化,InnoDB 存储引擎就是用 B+Tree 实现其索引结构。它带来的变化点:

  • B+树每个节点可以包含更多的节点,这样做有两个原因,一个是降低树的高度。另外一个是将数据范围变为多个区间,区间越多,数据检索越快
  • 非叶子节点存储key,叶子节点存储key和数据
  • 叶子节点两两指针相互链接(符合磁盘的预读特性),顺序查询性能更高

注:MySQL 的 InnoDB 存储引擎在设计时是将根节点常驻内存的,因此力求达到树的深度不超过 3,也就是说 I/O 不需要超过 3 次。

通常在B+Tree上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式环结构。因此可以对 B+Tree 进行两种查找运算:一种是对于主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找。

3.3 B-树和B+树的区别

  • B+树内节点不存储数据,所有数据存储在叶节点导致查询时间复杂度固定为 log n
  • B-树查询时间复杂度不固定,与 key 在树中的位置有关,最好为O(1)
  • B+树叶节点两两相连可大大增加区间访问性,可使用在范围查询等
  • B-树每个节点 key 和 data 在一起,则无法区间查找
  • B+树更适合外部存储(存储磁盘数据)。由于内节点无 data 域,每个节点能索引的范围更大更精确。

3.4 MongoDB 为什么使用B-树

B-树查询时间复杂度不固定,与 key 在树中的位置有关,最好为O(1)。尽可能少的磁盘 IO 是提高性能的有效手段。MongoDB 是聚合型数据库,而 B-树恰好 key 和 data 域聚合在一起。

至于MongoDB为什么使用B-树而不是B+树,可以从它的设计角度来考虑,它并不是传统的关系性数据库,而是以Json格式作为存储的nosql,目的就是高性能,高可用,易扩展。首先它摆脱了关系模型,上面所述的优点2需求就没那么强烈了,其次Mysql由于使用B+树,数据都在叶节点上,每次查询都需要访问到叶节点,而MongoDB使用B-树,所有节点都有Data域,只要找到指定索引就可以进行访问,无疑单次查询平均快于Mysql。

版权声明:本文为CSDN博主「布道」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/alex_xfboy/article/details/82818753

B+树 范围查询_一文读懂B树和B+树相关推荐

  1. hdfs读写流程_一文读懂HDFS分布式存储框架分析

    一文读懂HDFS分布式存储框架分析 HDFS是一套基于区块链技术的个人的数据存储系统,利用无处不在的私人PC存储空间及便捷的网络为个人提供数据加密存储服务,将闲置的存储空间利用起来,服务于正处于爆发期 ...

  2. mysql 默认事务隔离级别_一文读懂MySQL的事务隔离级别及MVCC机制

    回顾前文: <一文学会MySQL的explain工具> <一文读懂MySQL的索引结构及查询优化> (同时再次强调,这几篇关于MySQL的探究都是基于5.7版本,相关总结与结论 ...

  3. psm倾向得分匹配法举例_一文读懂倾向得分匹配法(PSM)举例及stata实现(一)

    原标题:一文读懂倾向得分匹配法(PSM)举例及stata实现(一) 一.倾向匹配得分应用之培训对工资的效应 政策背景:国家支持工作示范项目( National Supported Work,NSW ) ...

  4. java中date类型如何赋值_一文读懂java中的Reference和引用类型

    简介 java中有值类型也有引用类型,引用类型一般是针对于java中对象来说的,今天介绍一下java中的引用类型.java为引用类型专门定义了一个类叫做Reference.Reference是跟jav ...

  5. python输入什么就输出什么_一文读懂Python的输入和输出

    本文介绍了Python的输入和输出,既然是Python代码,那么就一定有输出量,那么,Python是如何输出的呢? 输出 用print()在括号中加上字符串,就可以向屏幕上输出指定的文字.比如输出'h ...

  6. gps导航原理与应用_一文读懂角速度传感器(陀螺仪)的应用场景

    前文我们大致了解陀螺仪的来历,原理和种类,那么,它与我们的日常生活有怎样的关系呢? 陀螺仪器最早是用于航海导航,但随着科学技术的发展,它在航空和航天事业中也得到广泛的应用.陀螺仪器不仅可以作为指示仪表 ...

  7. stata 求输出相关系数矩阵命令_一文读懂结果输出命令大全(上)

    目录 描述统计量 help tabstat   //Stata 官方命令 描述统计量组间均值差异检验 help ttest help ttable2 help estout 相关分析命令 help p ...

  8. 超融合和服务器关系_一文读懂超融合服务器

    原标题:一文读懂超融合服务器 1.什么叫超融合服务器 融合基础架构(Hyper-Converged Infrastructure)是一种集成了虚拟计算资源和存储设备的信息基础架构.在这样的架构环境中, ...

  9. python读取枚举_一文读懂Python 枚举

    enum是一组绑定到唯一常数值的符号名称,并且具备可迭代性和可比较性的特性.我们可以使用 enum 创建具有良好定义的标识符,而不是直接使用魔法字符串或整数,也便于开发工程师的代码维护. 创建枚举 我 ...

最新文章

  1. java统计字符串中每个字符出现的次数,统计字符串中每个字符出现的次数
  2. C++实现二叉搜索树的查找(附完整源码)
  3. Django ORM中原生JSONField的使用方法
  4. python读取指定行到最后一行_python读取文件最后一行两种方法
  5. 超70家影视传媒单位联合500余位艺人倡议:立即清理未经授权短视频
  6. 联想自带Y空间软件最好用的版本-可录屏无其它提示
  7. Keras 中文文档地址
  8. R语言如何做NMDS分析
  9. 樱桃键盘驱动linux,樱桃键盘mx board9.0驱动
  10. bzoj 3717 [PA2014]Pakowanie
  11. oracle to_char 进制转换_〖Oracle 转载〗Oracle的数据类型转换 to_char
  12. mybatis-plus配置(包含分页插件)
  13. 【技巧分享】【数据分析】数据分析模型
  14. 阿里云视频点播上传与url播放
  15. DS1302基本的读写
  16. Scala中Either两个子类Left/Right
  17. 模拟器Active Sync同步使用pc网络
  18. PYNQ官方镜像配置
  19. 软件开发、系统定制、小程序等怎么报价?
  20. python多线程详解 Python 垃圾回收机制

热门文章

  1. 星号替换手机号码的中间四位数
  2. 【警告】chunk base [mini-css-extract-plugin] Conflicting order between:
  3. 安卓破解视频教程合集
  4. 【Linux】shell脚本实战-各类运算符介绍
  5. creo动画如何拖动主体_Creo如何制作关键帧动画?
  6. creo 计算机配置,config配置文件乱码,creo配置文件config
  7. python创建socket对象_python socket对象内建方法
  8. mysql join union_MySQL JOIN UNION
  9. 教你用CAD制作一个简单的3D外壳
  10. 从KubeOperator开启k8s之旅