数据结构之B树、B+树、B*树

1、应用背景

二叉查找树、AVL树、红黑树等都属于二叉树的范围,查找的时间复杂度是O(log 2N),与树的深度相关,那么降低树的深度自然会提高查找效率。
但是我们面对这样一个实际问题:大规模数据存储中,树节点存储的元素数量是有限的(如果元素数量非常多的话,查找就退化成节点内部的线性查找了),这样导致二叉查找树结构由于树的深度过大而造成磁盘I/O读写过于频繁,进而导致查询效率低下。
因此,为了减少磁盘I/O的次数,必须降低树的深度,将“瘦高”的树变得“矮胖”。一个基本的想法就是:

  • 每个节点存储多个元素
  • 摒弃二叉树结构,采用多叉树

这样就引出来了一个新的查找树结构 ——多路查找树。根据AVL树给我们的启发,一颗平衡多路查找树可以使得数据的查找效率保证在O(logN)这样的对数级别上。

1.1 机械硬盘结构

为什么树的深度会与磁盘I/O相关呢?这要从硬件层面来说明。
机械硬盘的结构图如下:
《数据结构之B树、B+树、B*树》
硬盘中一般会有多个盘片组成,每个盘片包含两个面,每个盘面都对应地有一个读/写磁头。
每个盘面都被划分为数目相等的磁道,并从外缘的“0”开始编号,具有相同编号的磁道形成一个圆柱,称之为磁盘的柱面
《数据结构之B树、B+树、B*树》
盘面中一圈圈灰色同心圆为一条条磁道,从圆心向外画直线,可以将磁道划分为若干个弧段,每个磁道上一个弧段被称之为一个扇区。扇区是磁盘的最小组成单元,通常是512字节,不过由于不断提高磁盘的大小,部分厂商设定每个扇区的大小是4096字节。
顺便多说一句,以上图片是老式机械硬盘的示意图,每个磁道的扇区弧长是不一样的。越靠内的磁道密度越大,存储的数据也就越多;越靠外的磁道密度越小,存储的数据也就越少。所以,虽然内外磁道的扇区弧长不一样,由于密度的原因,每个扇区存储的数据量仍然是一样的。然而在新式磁盘中,内外磁道的扇区密度都是相同的,所以新式磁盘每个扇区的弧长都是一样的。

1.2 读写原理

当硬盘驱动器执行读/写功能时,盘片绕主轴高速旋转,当磁道在磁头)下通过时,就可以进行数据的读 / 写了。
系统将文件存储到磁盘上时,按柱面、磁头、扇区的方式进行,即最先是第1磁道的第一磁头(也就是第1盘面的第1磁道)下的所有扇区,然后,是同一柱面的下一磁头,……,一个柱面存储满后就推进到下一个柱面,直到把文件内容全部写入磁盘。
系统也以相同的顺序读出数据。读出数据时通过告诉磁盘控制器要读出扇区所在的柱面号、磁头号和扇区号(物理地址的三个组成部分)进行(目前多是通过LBA线性寻址的方式定位)
由于存储介质的特性,磁盘本身存取就比主存慢很多,再加上机械运动耗费(磁盘旋转和磁头移动),磁盘的存取速度往往是主存的几百分之一,因此为了提高效率,要尽量减少磁盘I/O。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。
预读的长度一般为(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4k),主存和磁盘以页为单位交换数据。当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行(详情请参考页面置换算法以及虚拟内存)。

1.3 响应时间

磁盘读取响应时间有三部分组成:

  • 寻道时间:磁头从开始移动到数据所在磁道所需要的时间,寻道时间越短,I/O操作越快,目前磁盘的平均寻道时间一般在3-15ms,一般都在10ms左右,这部分的时间代价最高
  • 旋转延迟:盘片旋转将请求数据所在扇区移至读写磁头下方所需要的时间,旋转延迟取决于磁盘转速。普通硬盘一般都是7200rpm,慢的5400rpm,因此一般旋转一圈大约8.3ms
  • 数据传输时间:数据通过系统总线传送到内存的时间, 一般传输一个字节大概0.02us

从上面的指标来看,其实最重要的,或者说我们最关心的应该只有两个:寻道时间与旋转延迟。为提高磁盘传输效率,软件层面应着重考虑减少寻道时间和延迟时间。
磁盘读取数据是以盘块(block)为基本单位的。位于同一盘块中的所有数据都能被一次性全部读取出来。而磁盘IO代价主要花费在查找时间寻道时间上。因此我们应该尽量将相关信息存放在同一盘块,同一磁道中。或者至少放在同一柱面或相邻柱面上,以求在读/写信息时尽量减少磁头来回移动的次数,避免过多的寻道时间。

所以,在大规模数据存储方面,大量数据存储在硬盘中,而在硬盘中读取/写入块(block)中某数据时,首先需要定位到磁盘中的某块,如何有效地查找硬盘中的数据,需要一种合理高效的外存数据结构,就是下面所要重点阐述的B树以及相关变种B+树及B*树。

2、B树

B树(Balance Tree)由Rudolf Bayer, Edward M. McCreight于1970发表的一篇论文《Organization and Maintenance of Large Ordered Indices》中首次提出。
一棵m阶的B 树的特性如下:

  • 根结点至少有两个子女。
  • 每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m
  • 每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m
  • 所有的叶子结点都位于同一层。
  • 每个节点中的元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的值域分划。

对比前面介绍过的2-3树与2-3-4树,可以发现,其实2-3树就是m=3时的B树,而2-3-4树就是m=4时的B树,两者是B树的特例。

注意:切勿简单的认为一棵m阶的B树是m叉树,虽然存在四叉树,八叉树,KD树,以及/R树/R*树/等空间划分树,但与B树完全不等同。

一个3阶B树的示意图如下:
《数据结构之B树、B+树、B*树》
以上图为例,若查询的数值为5:
  第一次磁盘I/O:在内存中定位(与17、35比较),比17小,左子树;
  第二次磁盘I/O:在内存中定位(与8、12比较),比8小,左子树;
  第三次磁盘I/O:在内存中定位(与3、5比较),找到5,终止。
整个过程中,我们可以看出:比较的次数并不比二叉查找树少,尤其适当某一节点中的数据很多时,但是磁盘IO的次数却是大大减少。比较是在内存中进行的,相比于磁盘IO的速度,比较的耗时几乎可以忽略。所以当树的高度足够低的话,就可以极大的提高效率。相比之下,节点中的元素多点也没关系,仅仅是多了几次内存交互而已,只要不超过磁盘页的大小即可。
对于一颗节点为N,阶为M的子树,查找和插入需要logM-1N ~ logM/2N次比较。这个很好证明,对于阶为M的B树,每一个节点的子节点个数为M/2 到 M-1之间,所以树的高度在logM-1N至logM/2N之间。这种效率是很高的,对于N=62*1000000000个节点,如果度为1024,则logM/2N <=4,即在620亿个元素中,如果这棵树的度为1024,则只需要小于4次即可定位到该节点,然后再采用二分查找即可找到要找的值。

B树的查找、插入等操作对与上一篇中的的2-3树、2-3-4树类似,不再赘述。

3、B+树

B+树是B树的变形,与B树的区别在于:

  • 有k个子结点的结点必然有k个关键字
  • 非叶结点仅具有索引作用,跟记录有关的信息均存放在叶结点中。
  • 树的所有叶结点构成一个有序链表,可以按照关键码排序的次序遍历全部记录。

一棵3阶B+树如下所示:
《数据结构之B树、B+树、B*树》
B+树的优势在于查找效率上,下面具体说明。
首先,B+树的查找和B树一样,类似于二叉查找树。起始于根节点,自顶向下遍历树,在节点内部典型的使用是二分查找来确定这个位置。
不同的是:
(1)、B+树中间节点没有卫星数据(索引元素所指向的数据记录),只有索引,而B树每个结点中的每个关键字都有卫星数据;这就意味着同样的大小的磁盘页可以容纳更多节点元素,在相同的数据量下,B+树更加“矮胖”,I/O操作更少
B树的卫星数据:
《数据结构之B树、B+树、B*树》

B+树的卫星数据:
《数据结构之B树、B+树、B*树》
需要补充的是,在数据库的聚集索引(Clustered Index)中,叶子节点直接包含卫星数据。在非聚集索引(NonClustered Index)中,叶子节点带有指向卫星数据的指针。
(2)、其次,因为卫星数据的不同,导致查询过程也不同;B树的查找只需找到匹配元素即可,最好情况下查找到根节点,最坏情况下查找到叶子结点,所说性能很不稳定,而B+树每次必须查找到叶子结点,性能稳定。
(3)、在范围查询方面,B+树的优势更加明显。B树的范围查找需要不断依赖中序遍历。首先二分查找到范围下限,在不断通过中序遍历,知道查找到范围的上限即可。整个过程比较耗时。
而B+树的范围查找则简单了许多。首先通过二分查找,找到范围下限,然后同过叶子结点的链表顺序遍历,直至找到上限即可,整个过程简单许多,效率也比较高。
例如:同样查找范围[3-11],两者的查询过程如下:
B树的查找过程:
《数据结构之B树、B+树、B*树》

B+树的查找过程:
《数据结构之B树、B+树、B*树》

4、 B*树

B是B+树的变体,在B+树的非根和非叶子结点再增加指向兄弟的指针;
一棵3阶B
树如下所示:
《数据结构之B树、B+树、B*树》
B*树定义了非叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3。

    原文作者:B树
    原文地址: https://blog.csdn.net/u012152619/article/details/84669668
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞