一 B树的由来

B树指的是一类树,包括B-树,B+树,B*树等,是一种自平衡的搜索树,它类似普通的平衡二叉树,不同的一点是B树允许每个节点有更多的子节点。B树是专门为外部存储器设计的,如磁盘,它对于读取和写入大块数据有良好的性能,所以一般用在文件系统及数据库中。

1. 为什么不用二叉平衡树

传统用来搜索的平衡二叉树有很多,AVL树,红黑树等。这些树在一般情况下的查询性能非常好,但当数据量非常大的时候就无能为力了。数据量非常大时,内存不够用,大部分数据只能存放在磁盘上,只有需要的数据才加载到内存。一般而言内存的访问时间为50ns,而磁盘在10ms左右。速度相差了近5个数量级,程序大部分的时间阻塞在磁盘IO上。所以核心就是要减少磁盘IO次数。而像AVL树,红黑树这类平衡二叉树从设计上无法"迎合"磁盘。

上图是一颗简单的平衡二叉树,我们来看下为什么数据库和文件系统用b树而不用平衡二叉树:

(1) 它的平衡是通过旋转来实现的,而旋转是对整个树的操作,若部分加载到内存中则无法完成旋转操作。

(2) 平衡二叉树的高度比较大(log n), 这样逻辑上很近的节点实际可能非常远,无法很好地利用磁盘预读(空间的局部性原理)

2. 从"迎合"磁盘的角度来看看B树的设计

索引的效率实际上依赖于磁盘IO的次数,加快索引的办法就是有效地减少磁盘IO次数。相比于平衡二叉树每次将范围分割为两个区间,B树每次将范围分割成多个区间,区间越多,定位数据越快越精确。多叉降低了B树的高度(底数很大的log n,二叉是底数为2). 那么节点为区间范围,每个节点就比较大了。因此新建节点时,直接申请页大小的空间(磁盘时按照block分的,一般为512 byte。磁盘IO一次读取若干个block,我们称为一页,具体大小和操作系统有关,一般为4k,8k或16k),计算机内存分配是按页对齐的,这样一个节点只需要一次IO。那么多叉树的总IO次数也就缩减为log n次。

二 B-树

1. B-树的结构

上面是一颗B-树,B-树的插入和删除就不具体介绍了,很多资料都描述了这一过程。在普通平衡二叉树中,插入删除后若不满足平衡条件则进行 旋转 操作,而在B-树中,插入删除后不满足条件则进行分裂及合并操作。

2. B-树的查找

我们来看看B-树的查找,假设每个节点有 n 个 key值,被分割为 n+1 个区间,注意,每个 key 值紧跟着 data 域,这说明B-树的 key 和 data 是聚合在一起的。一般而言,根节点都在内存中,B-树以每个节点为一次磁盘 IO,比如上图中,若搜索 key 为 25 节点的 data,首先在根节点进行二分查找(因为 keys 有序,二分最快),判断 key 25 小于 key 50,所以定位到最左侧的节点,此时进行一次磁盘 IO,将该节点从磁盘读入内存,接着继续进行上述过程,直到找到该 key 为止。

三 B+树

1. B+树的结构

B+树是B-树的变种,它与B-树的不同之处在于:

  • 在B+树中,key 的副本存储在内部节点,真正的 key 和 data 存储在叶子节点上 。
  • n 个 key 值的节点指针域为 n 而不是 n+1

因为内节点并不存储 data,所以一般B+树的叶节点和内节点大小不同,而B-树的每个节点大小一般是相同的,为一页。

为了增加 区间访问性,一般会对B+树做一些优化。 
如下图带顺序访问的B+树。

三 B-树和B+树的区别

1. 时间复杂度

B+树节点不存储数据,所有data存储在叶节点导致查询时间负责度固定为log n。而B-树查询时间复杂度不固定,与key在树中的位置有关,最好为O(1)

下面为图示:

B-树

从上图可以看出,key 为 50 的节点就在第一层,B-树只需要一次磁盘 IO 即可完成查找。所以说B-树的查询最好时间复杂度是 O(1)

B+树

由于B+树所有的 data 域都在根节点,所以查询 key 为 50的节点必须从根节点索引到叶节点,时间复杂度固定为 O(log n)

2. 区间查找

B+树叶节点两两相连可大大增加区间访问性,可使用在范围查询等,而B-树每个节点key 和data在一起,则无法区间查找

B+树可以很好的利用局部性原理,若我们访问节点 key为 50,则 key 为 55、60、62 的节点将来也可能被访问,我们可以利用磁盘预读原理提前将这些数据读入内存,减少了磁盘 IO 的次数。 
当然B+树也能够很好的完成范围查询。比如查询 key 值在 50-70 之间的节点。

3. B+树更适合外部存储。由于内节点无 data 域,每个节点能索引的范围更大更精确

这个很好理解,由于B-树节点内部每个 key 都带着 data 域,而B+树节点只存储 key 的副本,真实的 key 和 data 域都在叶子节点存储。前面说过磁盘是分 block 的,一次磁盘 IO 会读取若干个 block,具体和操作系统有关,那么由于磁盘 IO 数据大小是固定的,在一次 IO 中,单个元素越小,量就越大。这就意味着B+树单次磁盘 IO 的信息量大于B-树,从这点来看B+树相对B-树磁盘 IO 次数少。

从上图可以看出相同大小的区域,B-树仅有 2 个 key,而B+树有 3 个 key。

三 为什么MongoDB索引选择B-树,而mysql索引选择B+树

1 mysql 和 MongoDB

mysql是传统的关系型数据库,而MongoDB是文档形的数据库,是一种nosql,它使用xml或json格式来保存数据,归属于聚合型数据库。(键值数据库也属于聚合型数据库,比如redis)

2 例子

从MongoDB及mysql 谈B/B+树的更多相关文章

  1. 从B 树、B+ 树、B* 树谈到R 树

    从B 树.B+ 树.B* 树谈到R 树 作者:July.weedge.Frankie.编程艺术室出品. 说明:本文从B树开始谈起,然后论述B+树.B*树,最后谈到R 树.其中B树.B+树及B*树部分由 ...

  2. 从B树、B+树、B*树谈到R 树

    从B 树.B+ 树.B* 树谈到R 树 作者:July.weedge.Frankie.编程艺术室出品. 说明:本文从B树开始谈起,然后论述B+树.B*树,最后谈到R 树.其中B树.B+树及B*树部分由 ...

  3. 【译】MongoDb vs Mysql—以NodeJs为例

    亲爱的读者,您可能想知道为什么要写关于MongoDb和MySql这篇文章.那是因为我与NodeJs开发人员讨论在应用程序中使用哪种数据存储作为主要的数据存储方式. 我看过很多评论都在争论这个问题. 有 ...

  4. [转载]从B 树、B+ 树、B* 树谈到R 树

    从B 树.B+ 树.B* 树谈到R 树 作者:July.weedge.Frankie.编程艺术室出品. 说明:本文从B树开始谈起,然后论述B+树.B*树,最后谈到R 树.其中B树.B+树及B*树部分由 ...

  5. mongodb,redis,mysql的区别和具体应用场景

    一.MySQL 关系型数据库. 在不同的引擎上有不同 的存储方式. 查询语句是使用传统的sql语句,拥有较为成熟的体系,成熟度很高. 开源数据库的份额在不断增加,mysql的份额页在持续增长. 缺点就 ...

  6. 从B 树、B+ 树、B* 树谈到R 树(转)

      作者:July.weedge.Frankie.编程艺术室出品. 说明:本文从B树开始谈起,然后论述B+树.B*树,最后谈到R 树.其中B树.B+树及B*树部分由weedge完成,R 树部分由Fra ...

  7. 树结构系列(四):MongoDb 使用的到底是 B 树,还是 B+ 树?

    文章首发于「陈树义」公众号及个人博客 shuyi.tech 文章首发于「陈树义」公众号及个人博客 shuyi.tech,欢迎访问更多有趣有价值的文章. 关于 B 树与 B+ 树,网上有一个比较经典的问 ...

  8. MySQL 为什么使用 B+ 树来作索引?

    什么是索引? 所谓的索引,就是帮助 MySQL 高效获取数据的排好序的数据结构.因此,根据索引的定义,构建索引其实就是数据排序的过程. 平时常见的索引数据结构有: 二叉树 红黑树 哈希表 B Tree ...

  9. mongodb,redis,mysql的区别和具体应用场景(转)

    一.MySQL 关系型数据库. 在不同的引擎上有不同 的存储方式. 查询语句是使用传统的sql语句,拥有较为成熟的体系,成熟度很高. 开源数据库的份额在不断增加,mysql的份额页在持续增长. 缺点就 ...

随机推荐

  1. 从零开始实现SSD目标检测(pytorch)(一)

    目录 从零开始实现SSD目标检测(pytorch) 第一章 相关概念概述 1.1 检测框表示 1.2 交并比 第二章 基础网络 2.1 基础网络 2.2 附加网络 第三章 先验框设计 3.1 引言 3 ...

  2. 2019暑期金华集训 Day1 数据结构

    自闭集训 Day1 数据结构 CF643G 用类似于下面的方法,搬到线段树上. 如何合并两个集合?先全部放在一起,每次删掉最小的\(cnt_i\),然后把其他所有的\(cnt\)都减去\(cnt_i\ ...

  3. mui Picker DtPicker 固定内容以及变动内容Picker 不同情况下的应用 提高效率

    目的是: 保证不同的Picker只创建一次,多次创建Picker系统不会自己销毁,X掉一个之后后面可能会出现下一个. 保证实现需求的情况下,优化代码,提高效率. 1.如果picker中的内容为定值 v ...

  4. mac 启动mysql

    sudo /usr/local/mysql/support-files/mysql.server stop sudo /usr/local/mysql/support-files/mysql.serv ...

  5. .vue的文件在vscode里面是白色?

    https://cnodejs.org/topic/58b8cac17872ea0864fee2ee 要装一个 vetur的插件

  6. Hive和Hadoop

    我最近研究了hive的相关技术,有点心得,这里和大家分享下. 首先我们要知道hive到底是做什么的.下面这几段文字很好的描述了hive的特性: 1.hive是基于Hadoop的一个数据仓库工具,可以将 ...

  7. 关于linux下的系统存储管理

    https://blog.csdn.net/aaaaaab_/article/details/80159871 //查看当前系统磁盘使用空间 df -h //查看当前目录文件占用空间大小 du -sh ...

  8. 数据库连接池配置(案例及排查指南) 原创: 有赞技术 有赞coder 4天前

    数据库连接池配置(案例及排查指南) 原创: 有赞技术 有赞coder 4天前

  9. Redis 单线程却能支撑高并发 - 简书 https://www.jianshu.com/p/2d293482f272

    小结: 1.在 I/O 多路复用模型中,最重要的函数调用就是 select,该方法的能够同时监控多个文件描述符的可读可写情况:2.Redis 服务采用 Reactor 的方式来实现文件事件处理器(每一 ...

  10. Webservice初体验:axis调用wsdl和document解析

    Neo君遇到了需要调用webservice接口的情况,然而作为一只小白对这方面了解困乏,经过摸索,完成了一个小的Demo,记录下. 一:背景 同事给了我一个webservice地址,打开后后缀是&qu ...