B+B*树

Posted ych9527

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了B+B*树相关的知识,希望对你有一定的参考价值。

1.什么是B+树

B树是对B-树的优化和变形,也是一种多路搜索树,其定义和B-树基本相同,差别如下:

  • 每个节点中关键字的数量和孩子数量相等

    • 根节点的关键字数量为[1,M]
    • 非根节点关键字数量为[M/2,M]
  • 所有的值都会出现在叶子节点上,并且所有的叶子节点都会用一个指针链接起来(方便遍历),因此只需要遍历叶子节点即可。非叶子节点中只保存key,相当于路径索引。父亲中的存的key是由孩子的最小值组成

  • B+树的搜索与B-树基本相同,区别是B+树只有达到叶子节点才能命中(B-树可以在非叶子节点中命中),其性能也等价于在关键字全集做一次二分查找。

2.B+树的特性

  1. 所有关键字都出现在叶子节点的链表中(稠密索引),且链表中的节点都是有序的。
  2. 不可能在非叶子节点中命中。
  3. 非叶子节点相当于是叶子节点的索引(稀疏索引),叶子节点相当于是存储数据的数据层。
  4. 更适合文件索引系统

3.B+树的插入过程

M=3,需要插入5,6,4,8,7,10,36,16,4

image-20210717172116010

4.B+树查找的优点

  • B+树的优势主要体现在查询性能上

  • B-树的每个节点都有卫星数据(索引元素指向的数据记录),B+树中间节点没有卫星数据,这就意味着同样大小的磁盘页,B+树可以容纳更多的节点 -> B+树比B-树更加的矮胖,即IO的次数更少

  • 性能上B+树也更加稳定,因为B-树只需要找到匹配元素即可,B+树必须查询到叶子节点

  • 范围查询更便捷

image-20210717171213883

5.B*树

B*树是B+树的变形,在B+树的非根和非叶子节点再增加指向兄弟节点的指针

image-20210717171533612

image-20210717173217019

  • B树定义了非叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3(代替B+树的1/2);
  • B*树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了)
  • 如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针。 所以,B * 树分配新结点的概率比B+树要低,空间使用率更高

6.小结

  • B-树:多路搜索树,每个结点存储M/2到M个关键字,非叶子结点存储指向关键字范围的子结点;所有关键字在整颗树中出现,且只出现一次,非叶子结点可以命中

  • B+树:在B-树基础上,为叶子结点增加链表指针,所有关键字都在叶子结点中出现,非叶子结点作为叶子结点的索引;B+树总是到叶子结点才命中

  • 相对于B树,B+树适合文件索引系统

    • B+树空间利用率更高,因为B+树的内部节点只是作为索引使用,而不像B-树那样每个节点都需要存储硬盘指针
    • 增删文件(节点)时,效率更高,因为B+树的叶子节点包含所有关键字,并以有序的链表结构存储,这样可很好提高增删效率
  • B*树:在B+树基础上,为非叶子结点也增加链表指针,将结点的最低利用率从1/2提高到2/3

7.数据库和B+树的关系

  • 建表的时候,服务器会先解析sql语句,那么每一张表都会对应一棵B+树表中的主键就是B+树的key(唯一的)
  • 利用主键进行查找,即利用B+树的特性进行查找,是非常快的
  • 如果非主键查找,就需要遍历整棵树,效率就会下降,不过相对于B树来说,B+树还是块的,直接从叶子节点开始找即可,B树还需要进行层序遍历
  • 如果非主键查找想要变快,可以针对查找的值建立索引,重新建立一棵B+树或者哈希表

image-20210717194210135

8.mysql两种引擎

8.1MyISAM

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

  • 事务

    假设有事件 A转账给B
    第一条语句:A-1万元
    第二条语句:B+1万元
    
    如果其中一条语句失败,就会出现问题,这时就需要事务
    => 执行两条sql语句之前,开启事务
       执行两条sql成功,则提交事务
       失败,则回滚事务
    
  • MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。下图是MyISAM索引的原理图:
    image-20210717195127696

  • 这里设表一共有三列,假设我们以Col1为主键,则图8是一个MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引文件仅仅保存数据记录的地址

  • 在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。如果我们在Col2上建立一个辅助索引,则此索引的结构如下图所示:
    在这里插入图片描述

  • MyISAM的索引方式也叫做“非聚集”(叶子节点存储的是地址,数据是分离的)的,之所以这么称呼是为了与InnoDB的聚集索引区分

8.2InnoDB

  • InnoDB存储引擎,支持事务,其设计目标主要面向在线事务处理的应用,从MySQL数据库5.5.8版本开始,InnoDB存储引擎是默认的存储引擎。InnoDB支持B+树索引、全文索引、哈希索引。但InnoDB使用B+Tree作为索引结构时,具体实现方式却与MyISAM截然不同
  • 第一个区别是InnoDB的数据文件本身就是索引文件。MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址InnoDB索引,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引
  • 第二个区别是InnoDB的辅助索引data域存储相应记录主键的值而不是地址,所有辅助索引都引用主键作为data域
  • 聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录
  • 最大区别:MyISAM不支持事务,InnoDB支持事务

image-20210717200247431

  • 上左图是InnoDB主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。
  • 与MyISAM索引的不同是InnoDB的辅助索引data域存储相应记录主键的值而不是地址。换句话说,InnoDB的所有辅助索引都引用主键作为data域(上右图)

参考文章链接:
链接1

链接2

链接3

以上是关于B+B*树的主要内容,如果未能解决你的问题,请参考以下文章

求数据结构 B-树与B+树及其操作的代码(C语言版)

B树Java代码实现以及测试

[Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3)][C. Playing Piano](代码片段

apriori片段代码

你真的懂树吗?二叉树AVL平衡二叉树伸展树B-树和B+树原理和实现代码详解...

你真的懂树吗?二叉树AVL平衡二叉树伸展树B-树和B+树原理和实现代码详解...