(转)B-树和B+树的应用:数据搜索和数据库索引

背景:彻底搞清楚B树。

B树

B-即为B树,B树和B+树的特征,区别

有关b树的特性,注意与后面的b+树区分:

  1. 关键字集合分布在整颗树中;
  2. 任何一个关键字出现且只出现在一个结点中;
  3. 搜索有可能在非叶子结点结束;
  4. 其搜索性能等价于在关键字全集内做一次二分查找

b+树,是b树的一种变体,查询性能更好。m阶的b+树的特征:

有n棵子树的非叶子结点中含有n个关键字(b树是n-1个),这些关键字不保存数据,只用来索引,所有数据都保存在叶子节点(b树是每个关键字都保存数据)。
所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
所有的非叶子结点可以看成是索引部分,结点中仅含其子树中的最大(或最小)关键字。
通常在b+树上有两个头指针,一个指向根结点,一个指向关键字最小的叶子结点。
同一个数字会在不同节点中重复出现,根节点的最大元素就是b+树的最大元素。

 B+树

1.B+树定义与特性

B+树是B-树的变体,也是一种多路搜索树:

其定义基本与B-树同,除了:

1).非叶子结点的子树指针与关键字个数相同;

2).非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树(B-树是开区间);

3).为所有叶子结点增加一个链指针;

4).所有关键字都在叶子结点出现

为了全面 这里给出网上另外一种说法:

 

一棵m阶的B+树和m阶的B树的差异在于:

      1.有n棵子树的结点中含有n个关键字; (而B 树是n棵子树有n-1个关键字)

      2.所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大的顺序链接。 (而B 树的叶子节点并没有包括全部需要查找的信息)

      3.所有的非终端结点可以看成是索引部分,结点中仅含有其子树根结点中最大(或最小)关键字。 (而B 树的非终节点也包含需要查找的有效信息)

 

下图给出典型的3阶B+树示例

 

 

 

 

B+的特性:

 

1).所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的;

 

2).不可能在非叶子结点命中;

 

3).非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层;

 

4).更适合文件索引系统

 

 

2.B+树的基本操作

 

1)查找操作

 

     对B+树可以进行两种查找运算:

 

  a.从最小关键字起顺序查找;

 

  b.从根结点开始,进行随机查找

 

  在查找时,若非终端结点上的剧组机等于给定值,并不终止,而是继续向下直到叶子结点。因此,在B+树中,不管查找成功与否,每次查找都是走了一条从根到叶子结点的路径。其余同B-树的查找类似。

 

2).插入操作

 

      B+树的插入与B树的插入过程类似。不同的是B+树在叶结点上进行,如果叶结点中的关键码个数超过m,就必须分裂成关键码数目大致相同的两个结点,并保证上层结点中有这两个结点的最大关键码。(算法见百度百科)

 

3)删除操作

 

      B+树的删除也仅在叶子结点进行,当叶子结点中的最大关键字被删除时,其在非终端结点中的值可以作为一个“分界关键字”存在。若因删除而使结点中关键字的个数少于m/2 (m/2结果取上界,如5/2结果为3)时,其和兄弟结点的合并过程亦和B-树类似。

 

 

 

PS:

 

a.不同于B+树只适合随机检索,B+树同时支持随机检索和顺序检索,在实际中应用比较多.

 

b.为什么说B+树比B 树更适合实际应用中操作系统的文件索引和数据库索引?

 

b+树相比于b树的查询优势:

B+tree的磁盘读写代价更低:B+tree的内部结点并没有指向关键字具体信息的指针(红色部分),因此其内部结点相对B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多,相对来说IO读写次数也就降低了;

B+tree的查询效率更加稳定:由于内部结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引,所以,任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当;

数据库索引采用B+树而不是B树的主要原因:B+树只要遍历叶子节点就可以实现整棵树的遍历,而且在数据库中基于范围的查询是非常频繁的,而B树只能中序遍历所有节点,效率太低。

 

二、B*树(这个网上介绍的甚少,教科书我也没有找到细致的介绍)

 

B*Tree是B+树的变体,在B+Tree的非根和非叶子结点(内结点)再增加指向兄弟的指针

 

 

B*树定义了非叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3(代替B+树的1/2);

 

B+树的分裂:当一个结点满时,分配一个新的结点,并将原结点中1/2的数据复制到新结点,最后在父结点中增加新结点的指针;B+树的分裂只影响原结点和父结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针;

 

B*树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了);如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针;

 

所以,B*树分配新结点的概率比B+树要低,空间使用率更高。

 

 

另外如要详细理解R树 网上的作者July的blog有详细介绍

 

 

B+树与B*树小结

从B树、B+树、B*树谈到R 树

ps:介绍的非常详尽,重点阅读下。


 

资料补充,参考另一篇博文:MySql数据库索引原理(总结性)

 

posted @ 2015-10-07 11:21  CS408  阅读(379)  评论(0编辑  收藏  举报