B树和B+树

摘要:
让我们比较一下B树和二进制搜索树的搜索过程:假设B树中的查询数量,我们需要查询元素9,对于B树,我们需要进行4次查询。B树和B+树的区别:这是因为B+树和B具有不同的存储结构。以m级树为例。不同的查询;在B树找到特定值后,它结束,而B+树需要通过索引找到叶节点

1.磁盘原理

 B树和B+树第1张

当磁盘需要读取某个地址数据的时候,首先会判断数据在哪个盘片上,确定好盘片之后呢,就开始选道,选道的过程就是通过伸展机械臂到数据对应的磁道(也就是圆环),再通过磁盘的旋转找到对应的扇区,最后用磁头读取这几个扇区的数据到内存中去,因此可以看到读取磁盘数据是非常的耗时耗力的,尤其这里是机械操作。

因此如果用BST的方式在磁盘上存取数据,就会存在两个问题:

(1)由于二叉树只有两个分支,如果数据量非常大的话,树的高度就会很大,如果被查找的数据处于比较深的位置,那么磁盘寻址次数会非常的高,假设磁盘寻址+读取一次需要的时间是10ms,那么如果有一百万条数据,二叉树的高度会在20左右,这样一次查找,需要0.2s,一次性要查找100个数据,就需要20s,这个效率在数据库查找中是不可接受的

(2)磁盘读取过程中,是一次性读取8个扇区的,每个扇区的大小是512个字节,即一次性读取4k大小(blocksize)的数据,

我们看看数据库是如何设计的,一般情况下,一条数据是在几百个字节左右,如果每次都只读取一条信息,那势必会造成大量的空间浪费。

解决办法:(1)将树的高度降低,(2)尽量使得每次磁盘读取都能够得到最多的信息,

B树和B+树第2张

磁盘旋转,磁头读取数据到内存中

B树和B+树第3张B树和B+树第4张

 数据库中的信息

 B树和B+树第5张

 2.B树

B-Tree是为磁盘等外存储设备设计的一种平衡查找树。因此在讲B-Tree之前先了解下磁盘的相关知识。

系统从磁盘读取数据到内存时是以磁盘块(block)为基本单位的,位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么

InnoDB存储引擎中有页(Page)的概念,页是其磁盘管理的最小单位。InnoDB存储引擎中默认每个页的大小为16KB,可通过参数innodb_page_size将页的大小设置为4K、8K、16K。

而系统一个磁盘块的存储空间往往没有这么大,因此InnoDB每次申请磁盘空间时都会是若干地址连续磁盘块来达到页的大小16KB。InnoDB在把磁盘数据读入到磁盘时会以页为基本单位,在查询数据时如果一个页中的每条数据都能有助于定位数据记录的位置,这将会减少磁盘I/O次数,提高查询效率。

B-Tree结构的数据可以让系统高效的找到数据所在的磁盘块。

为了描述B-Tree,首先定义一条记录为一个二元组[key, data]key为记录的键值,对应表中的主键值data为一行记录中除主键外的数据。对于不同的记录,key值互不相同。

通常,我们指定B树,需要指定其阶数(就是一个节点有多少个分叉),一棵m阶的B树,具有以下特性:

(1)每个节点最多m-1个关键字,也就是说,每个节点最多有m个分叉

(2)根节点最少可以有1个关键字,其他节点最少有B树和B+树第6张个关键字

(3)和平衡二叉树类似,关键字的左侧数据都比关键字小,关键字的右侧数据都比关键字大

B树和B+树第7张

 根节点有3个,4个分叉,10,50,90按从小到大排序

10的左侧的分叉是1和7,这是比10小的,10的右侧分叉是15和40,这是比10大的

可以看到,和二叉查找树还是很相似的,都是有序的,左孩子小,右孩子大,只是B树的一个节点可以有多个元素,且有多个分支。

B树和B+树第8张

3.B树的查询

为什么B树的查找效率会比二叉查找树高?

下面比较B树和二叉查找树的查找过程:

(1)在B树中的查询次数

B树和B+树第9张

假设,我们要查询元素9,对于B树,我们需要查询4次。

第一次比较:10 比较,比 10 小,所以再 10 的左孩子找。

B树和B+树第10张

 第二、三次比较:和 3 比较,比 3 大,这个时候我们还得和 7 比较。

B树和B+树第11张

 第四次比较:和 9 比较,相等,找到目标树,返回。

 B树和B+树第12张

 所以最终的结果需要 4 次比较。

 (2)在二叉树中的比较结果

也是需要4次比较

B树和B+树第13张

 同样都是四次比较,而且,B 树的每一个节点,如果存放的元素比较多,那么 B 树的比较次数会更多,为什么就说 B 的效率比 二叉查找树快呢?

确实,如果单单从比较次数看的话,二叉查找树确实不比 B 树差,不过你忽略了一个很重要的点,那就是磁盘的寻址加载次数。

我们知道,在把磁盘里的数据加载到内存中的时候,是以为单位来加载的,而我们也知道,节点与节点之间的数据是不连续的,所以不同的节点,很有可能分布在不同的磁盘页中

所以对于上面的二叉查找树,我们可能需要进行 4 次寻址加载,如图:

B树和B+树第14张

 而对于 B 树,由于 B 树的每一个节点,可以存放多个元素,所以磁盘寻址加载的次数会比较少,例如上面的例子中,用 B 树的话,只需要加载 3 次,如图:

 B树和B+树第15张

 在内存的运算速度是非常快的,至少比磁盘的寻址加载速度,快了几百倍,而我们进行数值比较的时候,是在内存中进行的,虽然 B 树的比较次数可能比二叉查找树多,但是磁盘操作次数少,由之前阐述的读取磁盘是机械操作,耗时耗力。

所以总体来说,还是 B 树快的多,这也是为什么我们用使用 B 树来存储的原因。

根据B类树的特点,构造一个多阶的B类树,然后在尽量多的在结点上存储相关的信息,保证层数尽量的少,以便后面我们可以更快的找到信息,磁盘的I/O操作也少一些,而且B类树是平衡树,每个结点到叶子结点的高度都是相同,这也保证了每个查询是稳定的

 实际上磁盘的加载次数,基本上是和树的高度相关联的,高度越高,加载次数越多,越矮,加载次数越少。所以对于这种文件索引的存储,我们一般会选择矮胖的树形结构。例如有 1000 个元素,如果是二叉查找树的话,高度可能高达 10 层,而如果用 10 阶 B 树的话,只需要三四层即可。

 B 树除了会用在少部分的文件索引(数据库索引)外,应用的最多的就是文件系统了。

 3.B+树

大部分文件索引或者数据库索引都是用 B+ 树的,而只有小部分才用 B 树。

由于B+树的数据都存储在叶子结点中分支结点均为索引方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引,而B树则常用于文件索引。

 B树和B+树第16张

一个m阶树为例:

(1)根结点只有一个,分支数量范围为[2,m];

(2)分支结点,每个结点包含分支数范围为[ceil(m/2), m];

(3)分支结点的关键字数量等于其子分支的数量减一,关键字的数量范围为[ceil(m/2)-1, m-1],关键字顺序递增;

(4)所有叶子结点都在同一层;

 注:ceil表示返回一个大于等于指定表达式的最小整数

其操作和B树的操作是类似的,不过需要注意的是,在增加值的时候,如果存在满员的情况,将选择结点中的值作为新的索引,还有在删除值的时候,索引中的关键字并不会删除,也不会存在父亲结点的关键字下沉的情况,因为那只是索引。

 B树和B+树的区别:

这都是由于B+树和B具有这不同的存储结构所造成的区别,以一个m阶树为例。

(1)关键字的数量不同;B+树中分支结点有m个关键字,其叶子结点也有m个,其关键字只是起到了一个索引的作用,但是B树虽然也有m个子结点,但是其只拥有m-1个关键字。

(2)存储的位置不同;B+树中的数据都存储在叶子结点上,也就是其所有叶子结点的数据组合起来就是完整的数据,但是B树的数据存储在每一个结点中,并不仅仅存储在叶子结点上。

(3)分支结点的构造不同;B+树的分支结点仅仅存储着关键字信息和儿子的指针(这里的指针指的是磁盘块的偏移量),也就是说内部结点仅仅包含着索引信息

(4)查询不同;B树在找到具体的数值以后,则结束,而B+树则需要通过索引找到叶子结点中的数据才结束,也就是说B+树的搜索过程中走了一条从根结点到叶子结点的路径。

参考:

高频面试题:什么是B树?为啥文件索引要用B树而不用二叉查找树?

免责声明:文章转载自《B树和B+树》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇基于MCP2515的Linux CAN总线驱动程序设计(三)VSCode搭建node + typescript开发环境下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

3. mysql 索引命中规则及优化

1.什么是索引 “索引(在mysql中叫键 key),是存储引擎快速找到记录的一种数据结构。” --- 《高性能MySQL》,例如innodb引擎使用的就是B+树。 2.索引类型 命令:show index from table_name; 查看索引详情。 主键索引 PRIMARY KEY: 一种特殊的唯一索引,不允许为null,一般建表时会创建主键,若...

cscope的用法

一,一般源文件中生成索引文件 为了方便使用,编写了下面的脚本来更新cscope和ctags的索引文件: #!/bin/shfind . -name "*.h" -o -name "*.c" -o -name "*.cc" > cscope.filescscope -bkq -i cscope.filesctags -R 这个命令会生成三个文件:c...

MySQL SQL优化

前言 有人反馈之前几篇文章过于理论缺少实际操作细节,这篇文章就多一些可操作性的内容吧。 注:这篇文章是以 MySQL 为背景,很多内容同时适用于其他关系型数据库,需要有一些索引知识为基础。 优化目标 1.减少 IO 次数 IO永远是数据库最容易瓶颈的地方,这是由数据库的职责所决定的,大部分数据库操作中超过90%的时间都是 IO 操作所占用的,减少 IO...

使用pandas筛选出指定列值所对应的行

在pandas中怎么样实现类似mysql查找语句的功能: select * from table where column_name = some_value; pandas中获取数据的有以下几种方法: 布尔索引 位置索引 标签索引 使用API 假设数据如下: import pandas as pd import numpy as np df =...

数据结构(一)树

树 是由n≥0 个结点组成的有穷集合以及结点之间关系组成的集合构成的结构,是一种一对多的数据结构。   特点: 1. 有且仅有一个结点没有前驱结点,该结点为树的根结点。 2. 除了根结点外,每个结点有且仅有一个直接前驱结点。 3. 包括根结点在内,每个结点可以有多个后继结点。 树的术语: 1. 结点的度:该结点拥有的子树的数目。 2. 树的度:树中结点度...

Oracle索引语句整理

转载:http://www.cnblogs.com/djcsch2001/articles/1823459.html 索引,索引的建立、修改、删除索引索引是关系数据库中用于存放每一条记录的一种对象,主要目的是加快数据的读取速度和完整性检查。建立索引是一项技术性要求高的工作。一般在数据库设计阶段的与数据库结构一道考虑。应用系统的性能直接与索引的合理直接有关。...