一、B+树是应文件系统所需而产生的一种B树的变形树

1. 定义(使用阶数m来定义)

  1. 除了根结点外,其他非终端结点最多有m个关键字,最少有⌈m/2⌉个关键字
  2. 结点中的每个关键字对应一个子树
  3. 所有的非终端结点可以看成是索引部分,结点中仅含有其子树根结点中最大(或最小)关键字
  4. 所有的叶子节点包含了全部的关键字以及指向含有这些关键字记录的指针,并且:

    • 同一叶子节点中的关键字按大小顺序排列
    • 相邻的叶子节点顺序链接(相当于是构成了一个顺序链表)
    • 所有叶子节点在同一层

2. 和B树的区别

对于非终端结点,关键字的个数与其子树的个数相同;不像B树,子树的个数总比关键字的个数多1。

所有的关键字及相应的指针都在叶子结点中;不像B树,有的关键字是在内部结点中。(换句话说,在B+树中,内部结点仅仅起到索引的作用。在搜索过程中,如果待查询的关键字和内部结点的关键字一致,那么搜索过程不停止,而是继续向下搜索这个分支)

  1. 关键字的数量不同:B+树中,对于非终端结点,关键字的个数与其子树的个数相同;而B树中,关键字的个数比子树的个数少1。
  2. 存储的位置不同:B+树中的数据都存储在叶子结点上,也就是其所有叶子结点的数据组合起来就是完整的数据;而B树的数据存储在每一个结点中。
  3. 非终端结点的构造不同:B+树的非终端结点仅仅存储着关键字信息和指向孩子的指针(这里的指针指的是磁盘块的偏移量),也就是说内部结点仅仅包含着索引信息。
  4. 查询不同:B树在找到具体的数值以后,则结束;而B+树则需要通过索引找到叶子结点中的数据才结束,也就是说B+树的搜索过程中走了一条从根结点到叶子结点的路径。

二、关于B+树的面试题

1. 为何B+树用于数据库索引?

B树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题。B树的其非终端结点同样存储着数据,因此如果我们要找到具体的数据,就需要进行一次中序遍历。正是为了解决这个问题,B+树应运而生。

B+树的数据都存储在叶子结点中,非终端结点均为索引,方便扫库,只需要遍历叶子结点即可实现整棵树的遍历。所以B+树更加适合在区间查询的情况,而且在数据库中基于范围的查询是非常频繁的,所以通常B+树用于数据库索引。

2. 为何相比于B树,B+树在文件系统和数据库系统中更具优势?

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

举个例子,假设磁盘中的一个盘块容纳16bytes,而一个关键字2bytes,一个关键字具体信息指针2bytes。一棵9阶B树(一个结点最多8个关键字)的非终端结点需要2个盘快。而B+树非终端结点只需要1个盘快。当需要把非终端结点读入内存中的时候,B树就比B+树多一次盘块查找时间(在磁盘中就是盘片旋转的时间)。

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

③B+树更有利于对数据库的扫描 
B树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题,而B+树只需要遍历叶子节点就可以解决对全部关键字信息的扫描,所以对于数据库中频繁使用的范围查询,B+树有着更高的性能。

7. B+树的更多相关文章

  1. B树——算法导论(25)

    B树 1. 简介 在之前我们学习了红黑树,今天再学习一种树--B树.它与红黑树有许多类似的地方,比如都是平衡搜索树,但它们在功能和结构上却有较大的差别. 从功能上看,B树是为磁盘或其他存储设备设计的, ...

  2. ASP.NET Aries 入门开发教程8:树型列表及自定义右键菜单

    前言: 前面几篇重点都在讲普通列表的相关操作. 本篇主要讲树型列表的操作. 框架在设计时,已经把树型列表和普通列表全面统一了操作,用法几乎是一致的. 下面介绍一些差距化的内容: 1:树型列表绑定: v ...

  3. 再讲IQueryable<T>,揭开表达式树的神秘面纱

    接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...

  4. HDU1671——前缀树的一点感触

    题目http://acm.hdu.edu.cn/showproblem.php?pid=1671 题目本身不难,一棵前缀树OK,但是前两次提交都没有成功. 第一次Memory Limit Exceed ...

  5. 算法与数据结构(十一) 平衡二叉树(AVL树)

    今天的博客是在上一篇博客的基础上进行的延伸.上一篇博客我们主要聊了二叉排序树,详情请戳<二叉排序树的查找.插入与删除>.本篇博客我们就在二叉排序树的基础上来聊聊平衡二叉树,也叫AVL树,A ...

  6. [C#] C# 知识回顾 - 表达式树 Expression Trees

    C# 知识回顾 - 表达式树 Expression Trees 目录 简介 Lambda 表达式创建表达式树 API 创建表达式树 解析表达式树 表达式树的永久性 编译表达式树 执行表达式树 修改表达 ...

  7. bzoj3207--Hash+主席树

    题目大意: 给定一个n个数的序列和m个询问(n,m<=100000)和k,每个询问包含k+2个数字:l,r,b[1],b[2]...b[k],要求输出b[1]~b[k]在[l,r]中是否出现. ...

  8. bzoj1901--树状数组套主席树

    树状数组套主席树模板题... 题目大意: 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[ ...

  9. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

  10. jquery-treegrid树状表格的使用(.Net平台)

    上一篇介绍了DataTable,这一篇在DT的基础之上再使用jquery的一款插件:treegrid,官网地址:http://maxazan.github.io/jquery-treegrid/ 一. ...

随机推荐

  1. 纯swift开发,弹幕,演唱会广告牌

    最近去了次演唱会,看见有人在用这个,刚好没事,我自己也写了一个. 顺手练一练swift,第一个纯swift开发工程. 支持字体大小切换,滚动速度切换,字体切换,字体颜色切换 工程Git:https:/ ...

  2. Win10 64位+VS2015+Opencv3.3.0安装配置

    Win10 64位+VS2015+Opencv3.3.0安装配置 1.我们首先下载VS2015.OpenCV3.3.0. 1.1 VS2015下载 在官网https://visualstudio.mi ...

  3. linux、SMART、Shell的学习

    Linux指令 useradd 添加用户 添加用户 -d 添加用户路径 -e 制定密码有效时间 -G -g 指定用户所属组 -c 指定一段用户描述 -s Shell文件指定用户的登录Shell -u ...

  4. MySQL----MySQL数据库入门----第二章 数据库和表的基本操作

    2.1 数据库和数据库表的创建 ①数据库的创建(在数据库系统中划分一块存储数据的空间): create database 数据库名称 [charset 字符集]: ②数据库表的创建 use 数据库名 ...

  5. vue-cli3详细config配置

    const path = require('path') module.exports = { publicPath: './', // vueConf.baseUrl, // 根域上下文目录 // ...

  6. SpringAOP的自定义注解实践

    springaop属于spring的重要属性,在java中有相当广泛的用途,大家一般都接触过aop实现事务的管理,在xml里配好声明式事务,然后直接在service上直接加上相应注解即可, 今天我们来 ...

  7. Python-type函数使用

  8. PHP单例模式理解

    话不多说,先上代码 <?php class User{ /* * 1.创建一个存放对象的私有化静态变量 * 2.私有化克隆方法 * 3.私有化构造方法 * 4.创建实例化对象的唯一入口 * * ...

  9. Spark RDD理解

    目录 ----RDD简介 ----RDD操作类别 ----RDD分区 ----宽依赖和窄依赖作用 ----RDD分区划分器 ----RDD到调度 返回顶部 RDD简介 RDD是弹性分布式数据集(Res ...

  10. PTA基础编程题目集6-3简单求和 (函数题)

    6-3 简单求和 (10 分) 本题要求实现一个函数,求给定的N个整数的和. 函数接口定义: int Sum(int List[],int N) 其中给定整数存放在数组List[]中,正整数N是数组元 ...