B树是数据库存储引擎使用的最多的存储结构之一。许多开源数据库系统也都大量使B用树作为存储结构,多年来已经证明它们能够胜任大多数使用场景。

早在1971年鲁道夫·拜尔(Rudolph Bayer)和爱德华·M·麦克立特(Edward M. McCreight)就提出了B树这种数据结构,并受到广泛的应用。到1979年,B树已经发展出了许多变种形式。

在深入讨论B树之前,让我们首先讨论一下传统搜索树,例如,二叉搜索树、2-3树和AVL树。

二叉搜索树(Binary Search Tree)

二叉搜索树(BST)是一种有序的内存数据结构,用于高效的键值查找。二叉搜索树由多个节点组成。每个树节点由一个键、一个与此键关联的值和两个子指针构成。二叉搜索树从一个称为根节点的节点开始,且一棵树只有一根节点。图2-1展示了一棵二叉搜索树。

图2-1

在二叉搜索树中搜索空间被每个节点划分成左子树和右子树。如图2-2,一个节点的键值总是大于它左子树所有节点的键值,同时总是小于它右子树所有节点的键值。

图2-2

从树的根节点沿左子树指针向下到达叶子层(没有子节点的节点),就可以找到树中包含最小键值的节点。类似地,沿右子树指针向下就可以找到树中包含最大键值的节点。通常,键值可以保存在树中的所有节点中,因此如果从根节点开始搜索,在到达树的最底层之前搜索键就可能被找的。

平衡二叉树

如果随机的插入数据到二叉树中,二叉树就可能处于一种不平衡的状态,即它的一个分支比另一个分支长。图2-3(b)展示了最差的这种情况,这时它更像一个链表。查询的时间复杂度也是和链表一样是线性的,而不像图2-3(a)二叉树具有对数的查询时间复杂度。

图2-3

上面的例子可能有一些极端,但是它很好的说明了为什么需要对二叉树进行平衡操作。即使不大可能所有的节点都出现在树的某一边,但是树的两边节点还是有很大概率处于不平衡状态,这将对搜索性能产生很大的影响。

如果二叉树的高度为log₂N(其中N是树的节点数目),同时左右子树的高度差不大于1, 这样的二叉树称为平衡二叉树。如果不对二次树做平衡操作,树的形状完全由插入删除操作的顺序决定,二次树在搜索性能上可能就不具有优势。

在平衡二叉树中,每个节点把搜索空间划分为原来的一半,所以时间复杂度是对数的:即O(log₂N);如果是非平衡二叉树,最差情况下所有节点都在树的某一边,这是时间复杂度就是线性的:即O(N)。

为了避免新节点总是被添加到某一分支上而造成树的不平衡,每次操作后都需要对树进行调整。保证树的高度总最小,每个分支上的节点数目都在允许的范围之内。调整的方法之一就是在添加或删除节点后做一个旋转操作,如果新节点使树处于不平衡状态(两个连续的节点都只有子节点),就以中间节点为旋转轴旋转另外两个节点。如图2-4,以中间节点(3)为转动它的父节点(5)和子节点(2),最终它的父节点成为它的右子节点。

图2-4

基于磁盘存储的树

前面我们讨论了非平衡二叉树在最坏情况下的查询时间复杂度是O(N),平衡二叉树时间复杂度为O(log₂N)。同时,由于二叉树的较低扇出数(每个节点允许的最大子节点数),平衡二叉树重新调整节点更新指针的频率非常高。因此二叉搜索树并不适合于作为存储在磁盘上的数据结构。

如果存储二叉搜索树在磁盘上,我们会面临下面几个问题。第一个问题就是局部性:因为节点是以随机的顺序添加的,不能保证新添加的节点是临近其父节点的,这就意味着指向子节点的指针有可能指向一个跨越多个磁盘扇区后的位置。当然这个问题可以通过分页二叉树(Paged Binary Trees)的方式在一定程度上缓解;另一个问题是二叉树的扇出数是2,需要执行O(log₂N)次查找才能定位需要查找的节点(即可能需要执行同样次数的磁盘扇区重定位),2-3树和所有低扇出数的树都具有这样的局限性。尽管它们是非常有用的内存数据结构,但是它们并不适合磁盘这样的外部存储的数据结构。

考虑以上这些问题我们可以得出一个结论,如果某种树具有如下特征将更适合磁盘存储:

  • 高扇出数:提高相邻键的局部性;
  • 低高度:减少磁盘页的重定位次数;

基于磁盘的结构

在前文讨论基于内存和基于磁盘的数据库系统时,我们已经提到了一些数据结构适合于磁盘存储,而有些适合作为内存数据结构。并不是所有的数据结构都适用于磁盘存储的,所以在为数据库系统选择数据结构的时候我们必须考虑存储介质的限制。

如果数据太多太大以至于无法全部保存在内存中时,基于磁盘的数据系统是唯一的选择。这时只能有一部分数据被缓存在内存中,其余数据必须要以一种能够高效访问的方式存储在磁盘上。

普通硬盘(Hard Disk Drives)

大多数传统算法和数据结构是针对使用最广泛的普通硬盘设计的,现在随着新的存储介质不断涌现,适合新存储介质的算法和数据结构(或修改已有算法和数据结构)也不断的出现。

对于普通磁盘,读写时需要旋转磁盘并把读写磁头移动到读写扇区。磁盘旋转和磁头移动都是机械操作,因此读写时定位扇区的开销非常高。但是,一旦定位扇区完成,读写连续扇区的数据成本会低很多。另外需要注意的是对于普通磁盘最小读写单元是一个扇区,典型扇区的大小在512比特到4K之间。

由于定位磁盘扇区的开销非常高,这也是为什么我们经常说磁盘顺序读写的性能要明显的优于磁盘随机读写。

固态硬盘(Solid State Drives)

固态硬盘是用固态电子存储芯片阵列而制成的硬盘。固态硬盘不需要磁盘片旋转,也不需要移动读写磁头到读写扇区,因此随机读写和顺序读写之间的性能并没有太大的不同。但由于迎接和操作系统预读和并行的机制的原因,有时顺序读写和随机读写性能也会有一些不同。图2-5是固态硬盘硬盘的物理组织结构,固态硬盘最小的读写单位是页。

图2-5

不管是普通硬盘还是固态硬盘,操作系统都抽象成块设备,操作系统屏蔽了磁盘内部结构并对磁盘数据进行缓存。因此即使应用只需要读取一个比特的数据,整个块或也的数据也会一同被读取。在设计适用于磁盘存储的数据结构时,这个因素也需要被考虑。

适合磁盘的数据结构

除了磁盘访问本身的开销之外,设计高效的磁盘存储数据结构的一个主要的限制是最小磁盘读取单位是块。为了追踪某个指针到达特定的位置,我们必须要读取指针所在整个块的数据。虽然有这样一个限制,但是我们可以改变数据结构的布局来克服这一点。

总而言之,设计适合磁盘存储的数据结构时我们必须要考虑目标磁盘的特异之处, 目标是尽量的减少磁盘访问。我们可以通过改进局部性、优化结构内部表示以及减少页外指针的数量来做到这一点。

由此我们可以得出结论:具有高扇出和低高度属性的树才是理想的磁盘存储数据结构,另外平衡时更新指针的数量也需要尽量的少。B树恰好包含了这些思想:增加节点扇出,降低树的高度,减少节点指针数量和平衡操作的频率。下一篇我们会具体讨论B树相关的内容。

分页二叉树(Paged Binary Trees)通过把相邻节点存储到磁盘同一页(如图2-6)来提高数据的局部性。这样只需要在已经读入的当前页中就可以找到指针指向的子节点。但是指针任然可能指向的是一些保存在其它页面的子节点,加载这些页面也会产生一些额外的开销。另外,平衡磁盘存储二叉树时可能会需要调整页面,这时相应节点的指针也需要更新。因此维护磁盘存储二叉树的开销也不可忽略。

图2-6


深入理解数据库系统(储存引擎概述1)

深入理解数据库系统之存储存引擎2(数据和索引)

b+树时间复杂度_深入理解数据库系统之存储存引擎(二叉搜索树)相关推荐

  1. b树删除节点每次只能删一个吗_深入理解数据库系统之存储存引擎(B树)

    二叉搜索树不适合应用到磁盘上,因为它的扇出数较低并且平衡时需要大量的节点重定位和指针更新.B树通过增加每个节点存储项的数量(高扇出)和减少频繁的平衡操作来解决这些问题.下面我们将讨论了B树的内部结构, ...

  2. 【数据结构】树与树的表示、二叉树存储结构及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树与哈夫曼编码、集合及其运算

    1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R ...

  3. C++ 第八节数据结构 第七节 ——二叉搜索树 AVL树 红黑树(底层原理图+模拟实现)

    第一次,C++和数据结构联合推出,倾情献上呦~~ 给个关注吧 23333~~~~~~(现在每天系统就给我一个机器人的粉丝量了55555~~~~~) 本节内容,我们将着重来探讨 二叉树 中特殊的两种树- ...

  4. 08_Python算法+数据结构笔记-二叉搜索树查询/删除-AVL树旋转/插入/应用-贪心算法

    b站视频:路飞IT学城 清华计算机博士带你学习Python算法+数据结构_哔哩哔哩_bilibili #71 二叉搜索树:查询 import randomclass BiTreeNode:def __ ...

  5. 详解 二叉搜索树-----AVL树

    二叉搜索树 根结点比左子树中所有结点都大 根结点比右子树所有结点都小 最小的元素在最左侧 最大的元素在最右侧 中序遍历有序 具有以上的特征的二叉树就是二叉搜索树也叫二叉排序数 二叉搜索树的操作 查找 ...

  6. 数据结构 --- c语言二叉搜索树(有序的树)

    二叉搜索树基础 左边的孩子节点 < 父节点的值,右边孩子节点 > 父节点的值 每棵二叉搜索树的子树也是一棵二叉搜索树 10 充当根节点 18 > 根节点,应该放在根节点的右边:3 & ...

  7. b+树时间复杂度_满二叉树、完全二叉树、二叉搜索树、平衡二叉树

    "存在即合理"为什么需要每种树,本文不再冗余的总结每种树太多性质,就说重点. 二叉树(Binary Tree)主要包括:满二叉树.完全二叉树.二叉搜索树.平衡二叉树 性质太多,定义 ...

  8. b+树时间复杂度_前端大神用的学习笔记:线段树和树状数组

    全文篇幅较长,细心理解一定会有收获的♪(^∇^*). 1|0线段树 1|1一些概念     线段树是一种二叉搜索树,每一个结点都是一个区间(也可以叫作线段,可以有单点的叶子结点),有一张比较形象的图如 ...

  9. l2-004 这是二叉搜索树吗? (25分)_什么是 “线段树” ?

    线段树是一个复杂的数据结构,比较难理解,也比较难解释清楚.在我将这个数据结构反复学习了五遍的时候,我终于有了信心写出这篇介绍线段树的文章.希望大家能够掌握这种数据结构. 这篇文章比较长,建议大家耐心阅 ...

最新文章

  1. flutter依赖某些插件,点击运行会出现错误
  2. 字符串匹配shiftand算法
  3. 无人驾驶矿山赛道单笔最大融资:踏歌智行完成2亿元B轮融资
  4. AWS — AWS CloudFormation
  5. 【C 语言】结构体 ( 结构体变量内存操作 | 通过 “ . “ 操作符操作结构体内存空间 | 通过 “ -> “ 操作符操作结构体内存空间 )
  6. java isodate格式_fmt:formatDate的输出格式详解
  7. MutationObserver详解
  8. php取整数余数,js取整数、取余数的方法
  9. c#复制包含子目录文件夹代码
  10. snmp的oid查询方法
  11. 8首次登陆与线上求助
  12. RTI_DDS自定义插件开发 5 专属区域(_xxEA)
  13. python qq群管理_Python selenium 加载并保存QQ群成员,去除其群主、管理员信息的示例代码...
  14. LimeSurvey(开源问卷调查)
  15. 2019计算机保研 中科院信工所夏令营+中科院软件所九推记录
  16. [虚树模板] 洛谷P2495 消耗战
  17. php中清除文本框,php如何清除文本框
  18. C语言笔记本电脑销售系统课设
  19. 低学历该如何逆袭,2023年给你一个赚钱翻盘路径
  20. 分享四个体验不错的云游戏平台—网易云游戏、腾讯云游戏、菜鸡云游戏、格莱云游戏

热门文章

  1. vb链接远程mysql数据库代码_vb链接远程mysql数据库代码
  2. 计算机count的功能是,全国计算机二级Access每日练习4
  3. python读取txt文件并画图
  4. 遗传算法对于神经网络的优生优育
  5. 【译】.NET Core 是 .NET 的未来
  6. 又一款4800像素手机曝光:vivo V15 Pro
  7. 【Go语言】【12】GO语言的结构体
  8. 更多的结构化命令(第十三章)
  9. 如何证明你的性能测试结果可信?
  10. SDL2源代码分析8:视频显示总结