原文地址http://www.kongch.com/2011/09/why-b-tree/
“文件存储要选用B+树这样的数据结构”——没记错的话,这是严蔚敏那本数据结构书上的一句结论。不知道是我没细看还是她没细讲,反正当时纯粹应试地记了这么个结论。
不求甚解终究不是一个好的学习态度,一直以来我都没有细想过这个事情,直到看到了这篇博文 http://blog.csdn.net/v_JULY_v/article/details/6530142。
此文信息量很大,值得mark下来慢慢精读。今天就暂记一下关于磁盘文件存储选用B+ tree这一点以前没深究过的问题。毕竟,好记性不如烂笔头,虽然这篇里面ctrl-v担当了比较多的任务……
另一个比较有趣的收获是终于知道没有B减树这个东西了。以前老看到B-树,以为对应着B+树,是B树的某一变种。但实际情况是:
B-树,即为B树。因为B树的原英文名称为B-tree,而国内很多人喜欢把B-tree译作B-树,其实,这是个非常不好的直译,很容易让人产生误解。如人们可能会以为B-树是一种树,而B树又是一种一种树。而事实上是,B-tree就是指的B树。
下面言归正传:
磁盘的构造
磁盘是一个扁平的圆盘(与电唱机的唱片类似)。盘面上有许多称为磁道的圆圈,数据就记录在这些磁道上。磁盘可以是单片的,也可以是由若干盘片组成的盘组,每一盘片上有两个面。如下图11.3中所示的6片盘组为例,除去最顶端和最底端的外侧面不存储数据之外,一共有10个面可以用来保存信息。
当磁盘驱动器执行读/写功能时。盘片装在一个主轴上,并绕主轴高速旋转,当磁道在读/写头(又叫磁头) 下通过时,就可以进行数据的读 / 写了。
一般磁盘分为固定头盘(磁头固定)和活动头盘。固定头盘的每一个磁道上都有独立的磁头,它是固定不动的,专门负责这一磁道上数据的读/写。
活动头盘 (如上图)的磁头是可移动的。每一个盘面上只有一个磁头(磁头是双向的,因此正反盘面都能读写)。它可以从该面的一个磁道移动到另一个磁道。所有磁头都装在同一个动臂上,因此不同盘面上的所有磁头都是同时移动的(行动整齐划一)。当盘片绕主轴旋转的时候,磁头与旋转的盘片形成一个圆柱体。各个盘面上半径相同的磁道组成了一个圆柱面,我们称为柱面 。因此,柱面的个数也就是盘面上的磁道数。
磁盘的读/写原理和效率
磁盘上数据必须用一个三维地址唯一标示:柱面号、盘面号、块号(磁道上的盘块)。
读/写磁盘上某一指定数据需要下面3个步骤:
(1) 首先移动臂根据柱面号使磁头移动到所需要的柱面上,这一过程被称为定位或查找 。
(2) 如上图11.3中所示的6盘组示意图中,所有磁头都定位到了10个盘面的10条磁道上(磁头都是双向的)。这时根据盘面号来确定指定盘面上的磁道。
(3) 盘面确定以后,盘片开始旋转,将指定块号的磁道段移动至磁头下。
经过上面三个步骤,指定数据的存储位置就被找到。这时就可以开始读/写操作了。
访问某一具体信息,由3部分时间组成:
● 查找时间(seek time) Ts: 完成上述步骤(1)所需要的时间。这部分时间代价最高,最大可达到0.1s左右。
● 等待时间(latency time) Tl: 完成上述步骤(3)所需要的时间。由于盘片绕主轴旋转速度很快,一般为7200转/分(电脑硬盘的性能指标之一, 家用的普通硬盘的转速一般有5400rpm(笔记本)、7200rpm几种)。因此一般旋转一圈大约0.0083s。
● 传输时间(transmission time) Tt: 数据通过系统总线传送到内存的时间,一般传输一个字节(byte)大概0.02us=2*10^(-8)s
磁盘读取数据是以盘块(block)为基本单位的。位于同一盘块中的所有数据都能被一次性全部读取出来。而磁盘IO代价主要花费在查找时间Ts上。因此我们应该尽量将相关信息存放在同一盘块,同一磁道中。或者至少放在同一柱面或相邻柱面上,以求在读/写信息时尽量减少磁头来回移动的次数,避免过多的查找时间Ts。
所以,在大规模数据存储方面,大量数据存储在外存磁盘中,而在外存磁盘中读取/写入块(block)中某数据时,首先需要定位到磁盘中的某块,如何有效地查找磁盘中的数据,需要一种合理高效的外存数据结构。这种结构可以使得在查找过程中,IO次数尽量的少。
B- 树
B 树又叫平衡多路查找树。
B 树中的每个结点根据实际情况可以包含大量的关键字信息和分支(当然是不能超过磁盘块的大小,根据磁盘驱动(disk drives)的不同,一般块的大小在1k~4k左右);这样树的深度降低了,这就意味着查找一个元素只要很少结点从外存磁盘中读入内存,很快访问到要查找的数据。相较于2叉树的优势就在于此了。
举个例子,为了简单,这里用少量数据构造一棵3叉树的形式,实际应用中的B树结点中关键字很多的。上面的图中比如根结点,其中17表示一个磁盘文件的文件名;小红方块表示这个17文件的内容在硬盘中的存储位置;p1表示指向17左子树的指针。
下面,咱们来模拟下查找文件29的过程:
(1) 根据根结点指针找到文件目录的根磁盘块1,将其中的信息导入内存。【磁盘IO操作1次】
(2) 此时内存中有两个文件名17,35和三个存储其他磁盘页面地址的数据。根据算法我们发现17<29<35,因此我们找到指针p2。
(3) 根据p2指针,我们定位到磁盘块3,并将其中的信息导入内存。【磁盘IO操作2次】
(4) 此时内存中有两个文件名26,30和三个存储其他磁盘页面地址的数据。根据算法我们发现26<29<30,因此我们找到指针p2。
(5) 根据p2指针,我们定位到磁盘块8,并将其中的信息导入内存。【磁盘IO操作3次】
(6) 此时内存中有两个文件名28,29。根据算法我们查找到文件29,并定位了该文件内存的磁盘地址。
分析上面的过程,发现需要3次磁盘IO操作和3次内存查找操作。关于内存中的文件名查找,由于是一个有序表结构,可以利用折半查找提高效率。至于3次磁盘IO操作时影响整个B树查找效率的决定因素。
当然,如果我们使用平衡二叉树的磁盘存储结构来进行查找,磁盘IO操作最少4次,最多5次。而且文件越多,B树比平衡二叉树所用的磁盘IO操作次数将越少,效率也越高。
B+树
B+-Tree是应文件系统所需而产生的一种B-tree的变形树。
一棵m阶的B+树和m阶的B树的差异在于:
1.有n棵子树的结点中含有n个关键字; (而B 树是n棵子树有n-1个关键字)
2.所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大的顺序链接。 (而B 树的叶子节点并没有包括全部需要查找的信息)
3.所有的非终端结点可以看成是索引部分,结点中仅含有其子树根结点中最大(或最小)关键字。 (而B 树的非终节点也包含需要查找的有效信息)
为什么B+树可以满足要求?
1) B+-tree的磁盘读写代价更低
B+-tree的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。
举个例子,假设磁盘中的一个盘块容纳16bytes,而一个关键字2bytes,一个关键字具体信息指针2bytes。一棵9阶B-tree(一个结点最多8个关键字)的内部结点需要2个盘快。而B+ 树内部结点只需要1个盘快。当需要把内部结点读入内存中的时候,B 树就比B+ 树多一次盘块查找时间(在磁盘中就是盘片旋转的时间)。
2) B+-tree的查询效率更加稳定
由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
B*-Tree
B*-tree是B+-tree的变体,在B+ 树非根和非叶子结点再增加指向兄弟的指针;B*树定义了非叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3(代替B+树的1/2)。给出了一个简单实例,如下图所示:
B+树的分裂:当一个结点满时,分配一个新的结点,并将原结点中1/2的数据复制到新结点,最后在父结点中增加新结点的指针;B+树的分裂只影响原结点和父结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针。
B*树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了);如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针。
所以,B*树分配新结点的概率比B+树要低,空间使用率更高;
总结
通过以上介绍,大致将B树,B+树,B*树总结如下:
B树:有序数组+平衡多叉树;数据存在于非叶子节点上
B+树:有序数组链表+平衡多叉树;数据只存在于叶子上。
B*树:一棵丰满的B+树。
走进搜索引擎的作者梁斌老师针对B树、B+树给出了他的意见:
“B+树还有一个最大的好处,方便扫库,B树必须用中序遍历的方法按序扫库,而B+树直接从叶子结点挨个扫一遍就完了,B+树支持range-query非常方便,而B树不支持。这是数据库选用B+树的最主要原因。
比如要查 5-10之间的,B+树一把到5这个标记,再一把到10,然后串起来就行了,B树就非常麻烦。B树的好处,就是成功查询特别有利,因为树的高度总体要比B+树矮。不成功的情况下,B树也比B+树稍稍占一点点便宜。 B树比如你的例子中查,17的话,一把就得到结果了。
有很多基于频率的搜索是选用B树,越频繁query的结点越往根上走,前提是需要对query做统计,而且要对key做一些变化。 另外B树也好B+树也好,根或者上面几层因为被反复query,所以这几块基本都在内存中,不会出现读磁盘IO,一般已启动的时候,就会主动换入内存。”
分享到:
相关推荐
B+树是一种自平衡的树数据结构,常被用于数据库和文件系统中作为索引结构。与B树相比,B+树的所有叶子节点都位于同一层,且叶子节点之间通过指针相互连接,这使得B+树非常适合范围查询和顺序访问。 #### 三、代码...
- 插入和删除操作可能导致B树结构发生变化,为了保持较好的性能,通常会采用一定的平衡策略来尽量让B树保持平衡状态。 #### B-树 B-树是一种自平衡的多路搜索树,主要用于数据库和文件系统的索引结构。 **特点:**...
数据结构中的B树和B+树是两种非常重要的自平衡查找树,它们主要应用于数据库索引和文件系统中,以高效地处理大量的数据查找、插入和删除操作。这两种数据结构都是为了解决磁盘等外部存储设备I/O操作效率低下的问题而...
1. **B+树结构** - **根节点**:B+树的根节点可以是叶节点,也可以是非叶节点,但通常至少包含两个子节点。 - **分支节点(非叶节点)**:非叶节点不存储实际数据,仅包含指向子节点的指针,以及每个子节点对应的...
在计算机科学领域,数据结构是编程的基础,B+树作为一种高效的数据索引结构,被广泛应用于数据库和文件系统中。本文将深入探讨如何在Java环境中实现B+树,包括其基本概念、特性以及如何用Java代码来构建和操作B+树。...
B+树(B+ Tree)是一种自平衡的树数据结构,广泛应用于数据库系统和文件系统中,用于高效地存储和检索大量数据。它的主要特点是所有数据都存储在叶子节点上,且叶子节点之间通过指针链接,使得遍历变得更加简单。 #...
B+树作为一种自平衡的树形数据结构,广泛应用于大型数据集的快速访问,尤其是当需要进行范围查询时。 B+树的基本概念: 1. **节点与叶子节点**:B+树的所有数据都存储在叶子节点中,非叶子节点仅作为索引使用,不...
B+树是一种自平衡的树数据结构,它经常被用来实现数据库和文件系统的索引。在数据库管理系统中,B+树因其高效性和稳定性而被广泛采用。 #### B+树定义 B+树具有以下特性: 1. **根节点只有一个**:根节点的分支...
B+树,全称为B-Plus Tree,是一种自平衡的树数据结构,广泛应用于数据库和文件系统中,用于高效地存储和检索大量数据。它的设计目标是减少磁盘I/O操作,因为磁盘读写速度远低于内存。B+树的特点在于其节点可以拥有多...
B树、B-树、B+树以及B树++和R树是数据库和文件系统中常用的高效数据结构,它们主要用于实现磁盘或其他外部存储的查找。这些数据结构的设计目标是减少磁盘I/O操作,提高数据访问速度,因为磁盘读写速度远慢于内存。 ...
B+树是一种高效的数据结构,尤其适用于大数据存储,如数据库索引。它的设计目标是减少磁盘或慢速存储设备的访问次数,因为这些设备的读写速度远低于内存。在【标题】"关于b+树的操作详细图解"和【描述】中提到的PPT...
基于B+树的简易数据库存储系统c++源码.zip基于B+树的简易数据库存储系统c++源码.zip基于B+树的简易数据库存储系统c++源码.zip基于B+树的简易数据库存储系统c++源码.zip基于B+树的简易数据库存储系统c++源码.zip基于B...
B+树和B-树是计算机科学中用于数据库和文件系统等数据存储的重要数据结构,它们主要用于高效地管理大量数据,特别是当数据需要在磁盘等慢速存储介质上进行操作时。这两种树都是自平衡的,能保持数据的有序性,并且在...
在IT领域,B+树(B Plus Tree)是一种常见的数据结构,广泛应用于数据库索引、文件系统以及其他需要高效检索的数据存储系统中。本研究主要探讨如何在Java编程语言中实现B+树算法,以理解其原理并应用到实际项目中。 ...
这个名为"C语言开发 BTREE 数据文件索引程序库.rar"的压缩包内容似乎包含了一个C语言实现的B+树索引库,能够支持基本的查找、插入和删除操作。 B+树是一种自平衡的多路搜索树,它的特点在于所有叶子节点都在同一层...
B+树的所有数据都存储在叶子节点,非叶子节点仅用于索引,这样保证了所有数据查询最终都会落在叶子节点上,简化了搜索过程。 在VS.NET 2003环境下编译通过的B+树演示程序,可能包含了以下组件: 1. 数据结构:实现B...
在数据库系统中,B+树(B Plus Tree)是一种高效的数据结构,广泛应用于数据库和文件系统的索引存储。B+树的设计目标是优化磁盘I/O操作,因为磁盘读写速度远慢于内存。其主要特点包括平衡的树结构、所有数据都存储在...
综上所述,基于持久性内存的单向移动B+树是一种有效的解决方案,它解决了传统B+树在PM环境中面临的失败原子性和持久化开销问题,为构建高效、可靠的存储系统提供了新的思路。随着PM技术的不断发展和广泛应用,这样的...
B树、B-树、B+树和B*树是数据库和文件系统中常见的数据结构,主要用于高效地存储和检索大量数据。它们都是自平衡的多路搜索树,能够保持数据的有序性,并且在插入、删除和查找操作时保持较高的效率。 1. **B树**:B...
B-树和B+树是两种重要的数据结构,主要用于数据库和文件系统的索引,它们能够高效地处理大量的数据,尤其适合磁盘等慢速存储介质。这两种数据结构都是多路平衡查找树,能够保持数据的有序性,同时通过减少磁盘I/O...