Lecture #08: Trees Indexes

refer to course

refer to Note

refer to Slide

cover


1. Table Indexes

table index 是一份表属性的副本,主要用来加速。

table index 主要权衡两个方面的因素

  • 维护的代价

  • 加速的效果


2. B+ Tree

B+Tree_attribute

B+ 树是一个自平衡的数据结构,查找插入等操作的事件复杂度通常在 $O(\log{n})$ ,并且这种数据结构针对比较大的数据块做了优化。

B+ 树是一个 M-叉搜索树有以下的特征:

  • 完美平衡(所有的叶子节点的层数都相同)

  • 除了根节点外,左右节点的有 M/2-1 <= #keys <= M-1

  • 所有有 k 个 key 的节点都有 k+1 个非空子节点。

B+Tree Example

在 B+ 树中,叶子节点是存储最后我们需要的 key 的地方。因此我们如果要依据叶子节点去寻找最终的 val 的话,有以下两种方法。

  1. 将 val 存在的地方用一个指针记录下地址

  2. 直接存储在叶子节点中。

B-Tree VS. B+Tree

B-树和B+树最主要区别是,B-树的 key 也存在于非叶子节点。因此B-树在利用存储空间上无疑相较于B+树更为优秀。

因此可能存在以下的一些问题。

  1. B-树在遍历的时候不得不在各个节点中来回跳跃。而B+树则可以直接扫描。

  2. B-树,在使用将 val 存储在节点中的方法可能会导致查询过慢。

可视化

https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html

INSERT

找到一个叶子节点进行插入。按照大小插入。

如果该节点有足够的空间容纳,那么则插入停止。如果没有足够的空间那么有以下两步操作。

  1. 将该节点以中间值对半分为两个节点。

  2. 将该中间值向上推给父节点。若没有父节点,则创造父节点。然后对父节点执行同样的操作。

DELETE

找到叶子节点进行删除。

如果该叶子节点删除了该 key 之后至少有一半的容量,那么删除停止。

如果该叶子节点只有 M/2-1 个 key 了,那么有以下两种策略

  • 尝试将隔壁节点的值拿过来。

  • 如果尝试失败那么则尝试将两个节点合并。

Selection Conditions

具有与树结构查询的优缺点。

Duplicate Keys

有两种方式来解决重复的 keys

  1. 在所有的 key 后面加入 recorid ID 来确保每个 key 都是独一无二的。

  2. 使用一个可以溢出的节点来保存这些重复的信息。
    溢出节点

Clustered Indexes

表通常依照 primary key 进行索引。

不过有一些数据库采用聚集索引,会为表加上一个隐藏的 primary key。别的数据库通常无法使用这个索引


3. B+ Tree Design Choices

Node Size

通常是存储设备越慢,采用的 node size 越大。

  • HDD: ~1MB

  • SSD: ~10KB

  • In-Memory: ~512B

Merge Threshold

一些 DBMS 不会总是合并那些 half full 状态的节点。

因为,如果延迟合并操作的话,那么可能会减少重新平衡的开销。

维持一些比较小的节点并且周期性的重构树可能会更好。

Variable length Keys

  1. 采用指针的方法,即在 B+树中仅仅存储指向值的指针。

  2. 采用可变长的节点。

  3. 将所有的值强制以一个固定大小存储在 B+ 树中。

  4. 采用 map 的形式来进行存储

  1. Linear

    • 线性的扫描节点
    • 可以采用 SIMD 的技术增加扫描的数据量。
  2. Binary
    采用二分法进行查找

  3. Interpolation
    通过值,从而知道位置在哪。
    interpolation


4. Optimizations

Prefix Compression

通过提取出相同前缀的方式来进行压缩。

prefix compression

Deduplication

在 index 不一定都是独一无二的所有的值中,可以通过将这些值合并为一个 key 。

deduplication

Suffix Truncation

这种方式是通过在节点中选出可以进行区分比较的小的前缀长度,从而达到查找的目的。

truncation 1

truncation 2

Pointer Swizzling

将 B+ 树中的 page id 固定在 buffer pool 中,可以避免重复的读 disk 进而加快速度。然后将 page id 的指针替换为在 memory 中的真实的值,这样就可以绕过 buffer pool 的转换,进行直接访问。

Bulk Insert

重建一个 b+ 树的方法最快的方法是从底层向上建树