Skip to content

第4章:B+ 树、哈希与索引选择

B+ 树结构

B+ 树内部节点保存分隔键和子指针,叶子保存索引项并常按顺序链接。高扇出使树高较小,查询通常读取从根到叶的一条路径。

叶子满时分裂并向父节点插入分隔信息;父节点也可能分裂,直到根。删除要维护占用规则,具体系统也可能采用延迟合并等策略,不能把一种教科书实现当成所有数据库行为。

代价与范围查询

假设每页可容纳约 200 个子指针,百万级索引项只需少量层级即可定位。根和高层节点常驻缓存后,随机查找的实际 I/O 还会更少。

B+ 树支持有序范围扫描:先找到下界,再沿叶子遍历。哈希索引适合等值定位,但通常不能凭散列值高效回答原键顺序区间。

复合索引

索引 (cid,score) 按 cid、再按 score 的字典序组织。条件 cid=7 AND score>=90 可形成连续区间;只有 score>=90 通常不能得到一个同样简单的连续区间。

覆盖索引包含查询所需字段时,可能减少回表。但索引维护增加写入、空间和缓存成本,不能给每列任意叠加索引后只期待收益。

聚簇与回表

聚簇组织使数据记录与某个键的顺序接近,有利于范围扫描。非聚簇索引可能产生许多分散的记录访问。若范围很大,按索引逐条回表可能比顺序扫表更贵。

例如查询命中一半记录,若记录几乎均匀分散在所有数据页中,即使索引能列出一半键,也可能最终读取几乎全部数据页,并额外支付索引访问成本。

Bloom filter

Bloom filter 用位数组和多个哈希函数判断元素可能存在。标准构造允许假阳性,不允许对已正确插入且未被错误删除的元素给出假阴性。

它可以在查磁盘结构前排除不可能命中的情况,但“可能存在”仍需真正查询。它既不是精确索引,也不负责返回记录位置。

练习

  1. WHERE cid=7 ORDER BY score 选择一个合理复合索引并解释。
  2. 为什么低选择性的查询可能采用全表扫描?
  3. Bloom filter 返回阳性后,为何仍要查实际数据?

上次更新: