索引与树索引

索引与树索引

索引是定义在存储表(Table)基础之上,有助于无需检查所有记录而快速定位所需记录的一种辅助存储结构。

【组成】:由一系列存储在磁盘上的索引项(index entries)组成,每一个索引项由两部分构成。

  • 索引字段:由存储表中某些列(通常是一列)中的值串接而成。通常存储了索引字段的每一个值(也有不是这样的)。索引字段类似于词典中的词条。
  • 行指针:指向存储表中包含索引字段值的记录在磁盘上的存储位置。行指针类似于词条在书籍、词典中出现的页码。

存储索引项的文件为索引文件,存储表的文件为主文件

索引文件与主文件.png

索引的特点

  • 在一个表上可以针对不同的属性或属性组合建立不同的索引文件,且可建立多个索引文件。索引字段的值可以是存储表中的任何一个属性的值或任何多个属性值的组合值。
  • 索引文件比主文件小很多。通过检索一个小的索引文件(可全部装载进内存),快速定位后,再有针对性的读取非常大的主文件中的有关记录。
  • 有索引时,更新操作必须同步更新索引文件和主文件。

索引的特点-更新操作.jpg

常见分类

  • 聚集索引与非聚集索引
  • 稠密索引与稀疏索引
  • 多级索引与多码索引

聚集索引

聚集索引也称为主索引,是指索引中邻近的记录在主文件中也是邻近存储的;该索引中键值的逻辑顺序决定了表中相应行的物理顺序。

聚集索引.jpg

非聚集索引

非聚集索引也称辅助索引,是指索引中邻近的记录在主文件中不一定是邻近存储的。

非聚集索引.jpg

稠密索引和稀疏索引

  • 对于主文件中每一个记录都有一个索引项与其对应,指明该记录在磁盘的位置。这样的索引称为稠密索引。
  • 对于主文件中部分记录,有索引项与其对应,这样的索引称非稠密索引或稀疏索引。

稠密索引和稀疏索引.jpg

问:稠密索引如何定位记录?

  • 候选键属性的稠密索引——先查索引文件,然后再依据符合要求索引的行指针,找到对应的主文件字段。

候选键属性的稠密索引.jpg

  • 非候选键属性的稠密索引。

非候选键属性的稠密索引.jpg

非候选键属性的稠密索引2.jpg

非候选键属性的稠密索引3.jpg

问:稀疏索引如何定位记录?

假设我们要定位索引字段值为 K 的记录。

  • 首先找到相邻的小于 K 的最大索引字段值所对应的索引项;
  • 接着从该索引项所对应的记录按照顺序进行存储表检索。

稀疏索引如何定位记录.jpg

例如我们要寻找 Downtown,在稀疏索引表中没有 Downtown 索引字段,此时先找到相邻的小于 Downtown 的最大索引字段值所对应的索引项(很拗口)—— Brighton。接着,我们从 Brighton 所对应的记录 A-217 开始,按照顺序对存储表进行检索,直到 A-215 发现不是 Downtown 终止检索。

通过上述步骤可知,稀疏索引的使用要求是主文件必须是按对应索引字段属性排序存储。相比稠密索引,稀疏索引空间占用更少,维护任务更轻(不需要给每一个记录都存储一个对应的索引项),但速度更慢(对于没有存储在索引文件中的记录,需要按顺序进行检索,对比稠密索引直接链接到对应记录,速度上要慢不少)。

【改进】:索引项的行指针不指向记录,而是指向记录所在存储块的指针,即每一存储块有一个索引项,而不是每条记录有一索引项。

多级索引

当索引项比较多时,可以对索引再建立索引,依此类推,形成多级索引。常见的多级索引形式,如 B树 / B+ 树索引,以树型数据结构来组织索引项等。

多码索引

索引字段由存储表的多个属性值组合在一起形成的索引。

B 树与 B+ 树索引

B 树和 B+ 树的出现是因为磁盘 IO 操作次数频繁的问题。众所周知,IO 操作的效率很低,在大量数据查询时,我们不能一下子将所有数据加载到内存中,只能逐一加载磁盘页以及每个磁盘页对应树的节点,造成大量磁盘 IO 操作(最坏情况下为树的高度)。

平衡二叉树由于树深度过大而造成磁盘 IO 读写过于频繁,进而导致效率低下。所以,为了减少磁盘 IO 的次数,想办法降低树的深度,将“瘦高”的树变得“矮胖”。一个基本的想法:

  • 每个节点存储多个元素;
  • 摒弃二叉树结构,采用多叉树。

这样就引出来了一个新的查找树结构 ——多路查找树。那么 B 树作为一种平衡多路查找树就诞生了。

B 树

B 树也称 B- 树,它是一颗多路平衡查找树。我们描述一颗 B 树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,一般用字母 m 表示阶数。当 m 取 2 时,就是我们常见的二叉搜索树。

一颗 m 阶的 B 树定义如下:

  • 每个结点最多有 m-1 个关键字。
  • 根结点最少可以只有 1 个关键字。
  • 非根结点至少有 m/2 - 1 个关键字。
  • 每个结点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。
  • 所有叶子结点都位于同一层,或者说根结点到每个叶子结点的长度都相同。

【B 树索引的特点】:

  • 索引字段值仅出现一次;
  • 指向主文件的指针可以出现在任何节点;
  • 所有节点才能覆盖所有键值的索引。

B 树索引.jpg

B+ 树索引

一种以树型数据结构来组织索引项的多级索引。

B+ 树是对 B 树的一种变形树,它与 B 树的差异在于:

  • 有 k 个子节点的节点必然有 k 个关键码;
  • 非叶节点仅具有索引作用,跟记录有关的信息均存放在叶节点中。
  • 树的所有叶节点构成一个有序链表,可以按照关键码排序的次序遍历全部记录。

EzzkTS.jpg

EzzCOP.jpg

EzzFw8.jpg

EzzpQI.jpg

B+ 树的查询

从上到下,从左到右磁盘块依次编号为 1,2,3…9。B+ 树的查找过程:

  1. 查找数据项 15,首先把磁盘块 1 由磁盘加载到内存,此时发生一次 IO。在内存中查找确定 15 小于 60,锁定磁盘块 1 的 P1 指针,内存时间因为非常短(相比磁盘的IO)可以忽略不计;
  2. 通过磁盘块 1 的 P1 指针的磁盘地址把磁盘块 2 由磁盘加载到内存,发生第二次 IO,15小于25,锁定磁盘块 2 的 P1 指针;
  3. 通过指针加载磁盘块 4 到内存,发生第三次 IO,同时内存中做二分查找找到 15,结束查询,总计三次 IO 操作。

B+ 树结构.png

B+ 树的插入

下面是一颗 5 阶B+ 树的插入过程,节点最少 2 个关键字,最多 4 个关键字。

  1. 依次往空树中插入 5、8、10 和 15。

B+ 树的插入1.png
2. 插入 16,此时已超过关键字的个数限制,所以要进行分裂。在叶子结点分裂时,分裂出来的左结点 2 个记录,右边 3 个记录,中间 key 成为索引结点中的 key,分裂后当前结点指向了父结点(根结点)。

B+ 树的插入2.png

当然我们还有另一种分裂方式,给左结点 3 个记录,右结点 2 个记录,此时索引结点中的 key 就变为 15。

  1. 插入 17 和 18,当前结点的关键字个数大于 5,进行分裂。分裂成两个结点,左结点 2 个记录,右结点 3 个记录,关键字 16 进位到父结点(索引类型)中,将当前结点的指针指向父结点。

B+ 树的插入3.png

  1. 插入若干数据后,再插入 7。

B+ 树的插入4.png

当前结点的关键字个数超过 4,需要分裂。左结点 2 个记录,右结点 3 个记录。分裂后关键字 7 进入到父结点中,将当前结点的指针指向父结点,结果如下图所示。

B+ 树的插入5.png

当前结点的关键字个数超过 4,需要继续分裂。左结点 2 个关键字,右结点 2 个关键字,关键字 16 进入到父结点中,将当前结点指向父结点,结果如下图所示。

B+ 树的插入6.png

B+ 树的删除

下面是一颗 5阶 B+ 树的删除工程。

B+ 树的删除1.png

  1. 删除 22,删除后叶子结点中key的个数大于等于2,删除结束,结果如下图所示。

B+ 树的删除2.png
2. 删除 15。

B+ 树的删除3.png

删除后当前结点只有一个 key,不满足条件,而兄弟结点有三个 key,可以从兄弟结点借一个关键字为 9 的记录,同时将父结点中的关键字由 10 更新为9,删除结束。

B+ 树的删除4.png

  1. 删除 7。
    B+ 树的删除5.png

当前结点关键字个数小于 2,(左)兄弟结点中的也没有富余的关键字(当前结点还有个右兄弟,不过选择任意一个进行分析就可以了,这里我们选择了左边的),所以当前结点和兄弟结点合并,并删除父结点中的key,当前结点指向父结点。

B+ 树的删除6.png

此时当前结点的关键字个数小于 2,兄弟结点的关键字也没有富余,所以父结点中的关键字下移,和两个孩子结点合并,结果如下图所示。

B+ 树的删除7.png

Q&A

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

【答】:

  1. B+ 树的磁盘读写代价更低;
  2. B+ 树的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对 B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说 IO 读写次数也就降低了;举个例子,假设磁盘中的一个盘块容纳 16 bytes,而一个关键字 2 bytes,一个关键字具体信息指针 2 bytes。一棵 9 阶 B-tree(一个结点最多 8 个关键字)的内部结点需要 2 个盘块。而 B+ 树内部结点只需要 1 个盘块。当需要把内部结点读入内存中的时候,B 树就比 B+ 树多一次盘块查找时间(在磁盘中就是盘片旋转的时间);
  3. B+树 的查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

总结

索引与树索引思维导图.png

参考

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 成长之路 设计师:Amelia_0503 返回首页