B树系列以及数据库中B树系列的应用

一、B树

B树概念

一种适合外查找的平衡m叉树。

B树的性质

1、根节点至少有两个孩子。

2、每个分支节点都包含k-1个关键字和k个孩子(m/2向上取整 <= k <= m)

3、叶子节点有k-1个关键字。

4、所有叶子节点在同一层。

5、所有节点中关键字从小到大。

6、每个节点结构(n,A0,K1,A1,K2,A2,… ,Kn,An)其中,Ki(1 ≤ i ≤ n)为关键字,Ai(0 ≤ i ≤ n)为孩子指针。

n满足m/2向上取整 <= n <= m

B树结构

B树的插入

基本原理

在m阶B树中,每个节点最多有m个孩子和m-1个关键字,所以在关键字数量等于m时就需要节点分裂。

分裂规则:找到中位数作父节点,左右两侧数据作兄弟。

举例

在3阶B树中

节点关键字数到3就要分裂

中位数75就作父亲

B树的删除

基本原理

节点关键字数量小于m/2时就要借数据。优先从父亲借,不够再向兄弟借。如果都借不到就要合并兄弟节点。这里不作过多解释。

B树的性能分析

对于一棵节点为N度为M的B树,查找和插入需要log{M-1}N ~ log{M/2}N次比较,这个很好证 明:对于度为M的B-树,每一个节点的子节点个数为M/2 ~(M-1)之间,因此树的高度应该在要 $log{M-1}N$和$log{M/2}N$之间,在定位到该节点后,再采用二分查找的方式可以很快的定位 到该元素。 B-树的效率是很高的,对于N = 62*1000000000个节点,如果度M为1024,则log{M/2}N <= 4,即在620亿个元素中,如果这棵树的度为1024,则需要小于4次即可定位到该节点,然后利用 二分查找可以快速定位到该元素,大大减少了读取磁盘的次数。

补充知识

在概念中我们提到,B树用于在外存中进行查找数据,那为什么之前学习的AVL树,哈希表不适合在外存中查找呢?

使用平衡二叉树搜索树的缺陷: 平衡二叉树搜索树的高度是logN,这个查找次数在内存中是很快的。但是当数据都在磁盘中时, 访问磁盘速度很慢,在数据量很大时,logN次的磁盘访问,并不快。(注意磁盘只是定位慢,并不是查找慢)

 使用哈希表的缺陷: 哈希表在一些极端场景下某个位置冲突很多,导致访问次数增加,甚至退化到O(N)水平。

那作为多叉平衡二叉树,降低高度就意味着减少磁盘定位次数,大大减少查找时间。

二、B+树

B+树对于B树的优化

1、分支节点的子树指针与关键字个数相同。

2、分支节点的子树指针p[i]指向关键字值大小在[k[i],k[i+1]]区间之间。

3、所有叶子节点增加一个链接指针链接在一起。

4、所有关键字及其映射数据都在叶子节点出现。

分支节点和叶子节点有重复值,分支节点是叶子节点的索引,即父节点中存的是孩子节点中的最小值,这样的结构是为了更加方便的找到目标数据大概范围。

而且因为叶子结点有指针相连,遍历全部数据更加简单。

B+树结构

B+树的特点

1、所有关键字都出现在叶子节点的链表中,且链表中的节点都是有序的。

2、不可能在分支节点中命中。

3、分支节点相当于是叶子节点的索引,叶子节点才是存储数据的数据层。

三、B*树

B*树作用

B*树的本质就是提高空间利用率,我们知道不论是B树还是B+树,节点的数据分裂一次是m/2,这样在数据量大的情况下其实有很多节点都空有m/2的位置未插入,浪费较多,而B*树的分裂原理可以提高空间利用率。

B*树分裂原理

当一个节点关键字满了,如果兄弟节点未满就把数据插入到兄弟节点(当然父节点的最小索引值也要发生改变)

当节点与他的兄弟都满了,开一个新节点存放前一个节点的后1/3数据和后一个节点的前1/3数据,作为两个节点的兄弟,更新父节点。

所以B*树关键字和孩子数量范围[2/3m,m]

四、B树系列总结

B树:有序数组+平衡多叉树

B+树:有序数组链表+平衡多叉树

B*树:一棵更丰满空间利用率更高的B+树

五、B树系列在内外存中对比其他搜索数据结构优劣

1、B树在内存中查找的劣势

空间利用率低

插入删除数据必然伴随数据的移动,在顺序表中的时间复杂度可想而知。

虽然高度降低,但是在内存中优化并不明显

2、B树在外存中的优势

例如若有1024阶B树和平衡二叉搜索树,查找1000000000个数据,一个是3次,一个是30次相差不大,但是在磁盘中定位3次和30次时间是相差极大的。

六、数据库中B树系列的应用

1、B+树在数据库中应用

在建表使B+树索引磁盘数据,建表的主键是B+树的key,B+树的value存放数据文件在磁盘中的地址。

2、B+树相比于B树作主键索引的优势

B+树的value都在叶子,遍历方便,查找区间比查找具体值快。

对于没有建立索引的字段,全表扫描查找比B树快。

分支节点存储key,一个分支节点空间占用小,可以尽可能多的加载到缓存。

3、MyISAM引擎介绍

MyISAM引擎是MySQL5.5.8版本之前默认的存储引擎,不支持事物,支持全文检索,使用B+Tree 作为索引结构,叶节点的data域存放的是数据在磁盘中的地址。

主键(Primary key)唯一,但是想要用别的字段进行查找就要用辅助索引(Secondary key),本质相当于用B+树把字段作key,value指向磁盘地址,再用sql语句就会提高效率。

作为主键的字段必须唯一,若不唯一在添加数据时会报错,解决办法可以用自增主键。

(注意索引是基于表,不是基于数据库)

4、InnoDB引擎介绍

InnoDB存储引擎支持事务,其设计目标主要面向在线事务处理的应用,从MySQL数据库5.5.8版 本开始,InnoDB存储引擎是默认的存储引擎。InnoDB支持B+树索引、全文索引、哈希索引。但 InnoDB使用B+树作为索引结构时,具体实现方式却与MyISAM截然不同。

第一个区别是InnoDB的数据文件本身就是索引文件。MyISAM索引文件和数据文件是分离的(非聚集索引), 索引文件仅保存数据记录的地址。而InnoDB索引,表数据文件本身就是按B+树组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录(聚集索引)。这个索引的key是数据表的主键,因此 InnoDB表数据文件本身就是主索引。

所以MyISAM是先找到索引文件,再在磁盘上找到数据文件,而InnoDB叶子结点包含完整数据(索引+数据)每个节点数据都是以文件形式存在于磁盘。

问题

在InnoDB中建立辅助索引时,索引树的value存放主键,由于是完整的数据,索引树与主键树的叶子结点数据不同无法映射。解决办法就是查找两次,第一次在索引树中找到主键,第二次在主键树中搜索找到的主键。

而MyISAM是在索引树中找到磁盘地址,在磁盘地址中查找数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值