CMU课程笔记整理:向量索引、倒排索引、跳表与布隆过滤器
一、索引与过滤器:技术定位的本质分野
1.1 问题背景
数据库查询场景中,数据检索需求可归纳为两大类:精准定位元组 与快速判断元素是否存在。传统 B+ 树索引能够实现元组定位,但伴随较高的查询开销与空间占用;而暴力遍历查询的效率又无法满足生产要求。为弥补单一数据结构在不同检索场景下的性能短板,数据库体系衍生出两类核心辅助结构------索引与过滤器,分别服务于元组定位与存在性预判两类截然不同的需求。
1.2 核心定义
- 索引:基于数据表部分属性构建的有序结构化数据结构,核心功能是定位具体元组在磁盘或内存中的存储地址。其典型代表为 B+ 树,适用于需要获取完整元组的业务场景。
- 过滤器:概率型数据结构,仅用于判断元素大概率是否存在于集合中,无法返回元素的具体存储位置。其核心价值在于查询前置预判、减少无效 IO,典型代表为布隆过滤器。
索引负责"精准找数据",过滤器负责"快速筛数据",二者搭配使用可大幅优化数据库整体查询性能。
二、概率型过滤器技术体系
2.1 布隆过滤器
2.1.1 设计动机
数据库中高频存在集合成员查询场景,例如判断缓存 key 是否存在、优惠券编码是否有效、用户 ID 是否已注册等。若使用哈希表或数组等传统结构,空间占用会随数据量线性增长,查询效率也随之下降。布隆过滤器应运而生,以极致的空间压缩与 O(1) 的查询速度,专门适配海量数据的存在性预判需求。
2.1.2 核心机制
布隆过滤器本质上是一个固定长度的二进制位图,初始化时所有位均为 0。其核心依赖 k 个相互独立的哈希函数完成插入与查询操作,全程不存储任何原始数据,仅标记位图的对应位置。
插入操作 Insert(x) :对目标 key 执行 k 次哈希运算,将位图中对应的 k 个位置置为 1。
查询操作 Lookup(x):对目标 key 执行相同的 k 次哈希运算,校验所有对应位是否均为 1。若全部为 1,则判定元素大概率存在;若任意一位为 0,则判定元素绝对不存在。
2.1.3 优劣分析
优势:空间极致压缩,仅用位图存储无冗余数据;插入与查询时间复杂度均为 O(1);无假阴性,筛选可靠性强。
局限:存在假阳性概率,无法实现 100% 精准判断;不支持直接删除操作(删除某一 key 的标记位会误修改其他 key 共享的标记位);位图长度固定,无法动态扩容。
应用场景:数据库缓存穿透防护、优惠券有效性预判、磁盘查询前置过滤,可大幅减少无效磁盘 IO。
2.2 计数布隆过滤器
原生布隆过滤器不支持删除操作,无法适配需要动态增减数据的业务场景。计数布隆过滤器将二进制位图替换为整数计数器数组来克服这一缺陷:插入 key 时对应哈希位置的计数器加 1,删除 key 时对应计数器减 1,查询时校验所有计数器是否大于 0。
该方案解决了删除问题并支持动态数据更新,但代价是空间开销大幅提升,不再具备原生布隆过滤器的极致轻量化特性。
2.3 布谷鸟过滤器
2.3.1 设计动机
计数布隆过滤器空间开销过大,业界需要一种兼顾动态增删、低空间占用与低误判率的新型过滤器。布谷鸟过滤器基于布谷鸟哈希表实现,不存储完整 key,仅存储 key 的指纹(fingerprint)信息,每个 key 对应两个哈希桶,桶满时通过迁移已有元素指纹来完成插入。
2.3.2 双位置计算机制
针对任意待操作元素,布谷鸟过滤器通过以下步骤计算两个可选存储位置:
- 通过基础哈希函数计算得到第一个位置 i1i_1i1;
- 计算元素对应的指纹(fingerprint);
- 基于指纹再次哈希并结合异或运算推导出第二个位置 i2i_2i2。
该机制具备一个关键特性:已知任意一个位置和指纹,即可反向算出另一个备用位置。每个元素拥有两个备选位置,极大降低了哈希冲突概率,也为元素迁移与删除提供了基础支撑。
2.3.3 三大基础操作
插入:计算元素指纹与两个备选位置;优先检查两个位置是否存在空闲位,若有则直接存入;若均被占用,则随机选取一个位置将原有指纹"驱逐",存入当前元素指纹;被驱逐的指纹重新计算自身备用位置,重复上述占位与驱逐流程。系统设置最大驱逐次数阈值,超过阈值仍未完成放置则判定过滤器已满,插入失败。
查询:计算待查询元素的指纹与两个对应位置,依次检查两位置内的指纹。若两位置均无匹配指纹,则元素一定不存在(无假阴性);若任意一个位置匹配到指纹,则元素大概率存在(存在极低概率假阳性)。
删除:这是布谷鸟过滤器相较于布隆过滤器最核心的优势------支持安全删除。计算待删除元素的指纹与两个位置,在位置中定位匹配指纹后清空该位置即可完成删除。需要注意的是,删除操作的前提是待删除元素确实已存入过滤器,若元素不存在则盲目删除会误删其他数据的指纹。
2.3.4 应用案例与优劣
以广告投放场景为例:为每个推广活动创建一个布谷鸟过滤器,存储已参与活动的用户指纹。用户访问时过滤器快速判断是否已参与,未参与则推送广告,已参与则跳过;用户报名后动态删除对应指纹。
优势 :支持动态增删、空间效率优于计数布隆过滤器、假阳性率可控。
局限:哈希冲突迁移可能带来少量性能开销。
2.4 简洁范围过滤器
传统过滤器仅支持精准存在性查询,无法适配数据库范围查询与前缀匹配场景。SuRF 基于压缩字典树实现,是一种不可变过滤器,支持精准匹配、前缀匹配与范围过滤。
字典树通过分层前缀存储实现键的天然有序排列。范围查询时,只需沿树的层级匹配区间边界,裁剪掉所有超出范围的分支,即可高效遍历并获取区间内所有键。这种基于前缀有序结构的检索方式,使字典树成为唯一能高效支持范围查询与前缀匹配的基础结构,也是 SuRF 的核心实现原理。
优势 :唯一支持范围查询的轻量过滤器,查询精度高。局限:结构不可变,不支持动态数据修改。
三、内存有序索引技术
3.1 跳表
3.1.1 设计动机
数据库需要一种有序、可动态增删、无需重平衡的内存索引。基础有序链表实现简单,但所有操作均为线性遍历(O(n)),海量数据下性能极差;B+ 树需要频繁重平衡,内存维护开销大。跳表由此被提出,兼顾有序性、高性能与低维护成本。
3.1.2 多层结构
跳表本质是多层层有序链表,核心通过上层指针跳过大量无效数据实现快速检索。第 1 层存储全部有序 key,第 2 层存储 1/2 的 key,第 3 层存储 1/4 的 key------每一层节点数量均为下一层的 1/2,层级越高跳跃跨度越大。所有操作(查询、插入、删除)均从最高层开始遍历,快速定位目标区间后下沉至下层精准匹配。
3.1.3 删除操作:双阶段策略
跳表删除分为逻辑删除与物理删除两阶段,以保障并发安全:
- 逻辑删除:为目标节点设置删除标记(Del? = true),标记为"已删除"。此时节点仍存在于链表中,但后续所有线程访问时会直接跳过该节点。
- 物理删除:当确认没有任何线程持有该节点的引用时,从顶层到底层依次调整前驱节点的后继指针,断开与被删节点的连接,最终释放内存。
以删除 K₅ 为例:首先在各层为 K₅ 设置 Del? = true,确认无线程引用后,将 K₄ 的后继指针指向 K₆,断开 K₅ 的连接,各层链表恢复有序结构。这种双阶段方式既保证了线程安全,又避免了删除过程中的链表断裂问题。
3.1.6 优劣与应用
优势 :无需 B+ 树的全局重平衡操作,动态增删开销极低;无反向指针时内存占用小于 B+ 树;天然有序,适配范围查询。局限 :节点指针分散导致缓存局部性差,磁盘适配性极低,仅适合内存场景;反向查询实现复杂。典型应用:RocksDB、SingleStore、LSM 树的内存表(MemTable)。
3.2 字典树
B+ 树与跳表基于完整 key 做哈希或排序检索,对于前缀匹配与字符串检索场景效率低下。数据库中存在大量字符串 key(用户名、编码、前缀 ID)的检索需求,字典树基于 key 的二进制或字符前缀逐位检索来满足这一需求。
字典树又称前缀树,核心是按 key 的数字或字符前缀分层存储,无需存储完整 key,通过根节点到叶子节点的路径拼接出完整 key。树的形态仅由 key 的长度和前缀决定,与插入顺序无关,无需重平衡。所有操作复杂度为 O(k),k 为 key 的长度,与数据总量无关。
键跨度 是字典树的核心参数,指每一层节点表示的部分键位数(如 1 位或 2 位),直接决定两个关键特性:
- 节点扇出度 :即每个节点的子节点数量,若跨度为 n 位则扇出度为 2n2^n2n(1 位跨度对应 2 个子节点,2 位跨度对应 4 个子节点)。
- 树的物理高度:跨度越大,每层处理的位数越多,树高度越低;反之跨度越小,树高度越高。
优势 :前缀匹配与模糊查询性能极致;无需重平衡,动态更新稳定;key 隐式存储节省空间。局限:普通字典树节点稀疏,存在大量空指针导致空间利用率低;超长 key 会导致树高度过高。
3.3 基数树
普通字典树存在大量单叶子节点的冗余层级,空间浪费严重。基数树通过垂直压缩单链子节点------将连续只有单个子节点的多层节点合并为一个节点,大幅降低树高度。路径压缩的本质是将多个节点的公共前缀存储在一个节点中。
由于路径压缩,基数树在查询时可能出现假阳性(路径匹配但键不匹配),因此数据库在查询后必须回表校验原始数据以确保结果正确。Judy 数组、ART 索引、Masstree 均为自适应压缩的基数树变体,适配不同数据量和检索场景。
优势 :极致压缩空间,树高度远低于普通字典树,查询速度更快;支持精准匹配和范围查询。
局限:节点合并与拆分存在少量更新开销;存在检索假阳性需要二次校验。
四、全文检索:倒排索引
4.1 设计动机
传统有序索引(B+ 树、跳表)仅支持精准值与范围查询,无法适配文本关键词检索。例如业务需求"查询包含 Pavlo 关键词的文章",使用普通索引搭配 LIKE 模糊查询会触发全表扫描,性能极差。倒排索引专门解决全文检索场景,通过反向映射实现"关键词→包含该词的文档 ID 列表"的检索路径。
4.2 核心结构
倒排索引由词典和倒排记录表两大部分组成。词典存储所有关键词,每个关键词映射到一个文档 ID 列表。
4.2.1 词典层
顶层使用 B+ 树存储所有词项(Term),B+ 树的有序性支持高效的词项查找、前缀匹配和范围查询。每个词项通过指针映射到对应的倒排列表,实现"词项→记录集合"的快速定位。
4.2.2 倒排列表层
根据词项的文档频率采用两种存储方式:
- 低频词:直接存储排序后的记录 ID 列表,结构简单,读取速度快。
- 高频词:嵌套一层 B+ 树存储记录 ID,解决大规模列表线性扫描效率低下的问题,支持快速定位和范围过滤。
4.2.3 Pending List 层
这是 GIN 索引的关键优化,用于解决倒排索引频繁更新的性能瓶颈:新增和修改的记录先写入独立的日志中,不直接修改主索引;后台异步将日志中的变更合并到主索引,避免即时更新对主索引结构的频繁修改,提升并发写入性能。查询时会同时读取主索引和 Pending List,保证结果一致性。
4.2.4 主流实现
- Lucene:通过有限状态转换器(FST)存储词典,后台分段合并、增量更新,结合增量压缩算法节省空间。
- PostgreSQL GIN 索引:词典用 B+ 树存储,少量文档的关键词直接存 ID 有序列表,大量文档则嵌套 B+ 树存储。
倒排索引还支持 TF-IDF、BM25 算法做结果权重排序,支持 n 元分词实现模糊检索与拼写纠错。
4.3 优劣与应用
优势 :全文关键词检索性能碾压传统索引;支持模糊匹配、语义归一化、结果排序;主流数据库与检索引擎原生支持。
局限:索引构建与更新开销大,不适合高频更新的文本数据;仅适配文本检索,无法用于数值范围查询。
五、语义检索:向量索引
5.1 设计动机
倒排索引仅支持关键词字面匹配,无法实现语义相似检索。例如用户搜索"嘻哈说唱歌曲"时,需要匹配语义相近的 Wu-Tang Clan 相关作品,而非仅匹配固定关键词。随着 AI 嵌入向量技术普及,数据库需要支持浮点向量的近邻相似度查询,向量索引由此诞生。
5.2 核心实现
向量索引专门用于高维浮点向量的近邻搜索,核心是将文本、图片、音频转化为 AI 嵌入向量,通过向量相似度匹配实现语义检索,主要分为两类实现方案。
5.2.1 向量倒排索引
通过 K-means 聚类将海量向量划分为多个聚类簇,每个簇对应一个质心,构建"质心→簇内向量列表"的倒排映射。检索时先匹配最接近的聚类簇,仅扫描簇内向量,避免全量对比。同时支持向量量化降维以减少计算开销。
5.2.2 图向量索引
将每个向量作为图节点,与最近的 n 个向量建立边关联,构建多层层级图结构。检索时从顶层节点贪心遍历,逐步逼近目标向量,精准匹配最相似结果。
5.2.3 应用案例
将所有专辑歌词通过 AI 模型转化为多维浮点向量,语义相似的歌曲向量数值接近。用户输入"躲避警方的说唱歌曲",生成查询向量后,向量索引快速匹配相似度最高的专辑,实现语义检索而非关键词匹配。
5.3 优劣与应用
优势 :支持语义相似检索,突破传统文本关键词匹配限制;适配 AI 大模型向量数据库场景;分层或聚类优化后,亿级向量检索可实现毫秒级响应。
局限 :检索结果为概率相似结果,无绝对精准性;高维向量存储与计算开销大;索引构建成本高。
典型应用:智能问答、内容推荐、图片相似度检索、大模型知识库检索。
六、数据库索引高级优化技术
6.1 局部索引
业务中大量查询仅针对数据表的部分数据(如仅查询有效数据、近一年数据、指定标签数据)。全局索引会为全表数据构建索引,存在大量无效索引条目,空间浪费且更新开销大。
局部索引在构建时添加 WHERE 过滤条件,仅为满足条件的子集数据创建索引。例如 CREATE INDEX idx_foo ON foo(a,b) WHERE c='WuTang' 仅对 c 字段为 WuTang 的数据构建索引。常用场景为按时间分区索引(每月或每年单独建索引)。
优势 :索引体积大幅缩小、维护开销低、查询效率更高。局限:仅适配固定过滤条件的查询,场景通用性差。
6.2 索引包含列
普通索引仅存储索引字段,查询需要回表读取其他字段数据,产生磁盘 IO。对于高频简单查询,回表操作是主要性能瓶颈。
索引包含列通过 INCLUDE 关键字将查询所需的非索引字段附加到索引叶子节点,附加字段不参与索引排序、仅做数据存储。查询时所有所需字段均在索引中,无需回表,实现索引扫描(Index-only Scan)。
优势 :彻底消除回表 IO,大幅提升高频简单查询性能。局限:索引冗余存储数据,增加少量空间开销,不适合大范围字段包含场景。
七、技术选型总结
| 检索需求 | 推荐技术 | 核心优势 |
|---|---|---|
| 磁盘点查询 / 范围查询 | B+ 树 | 稳定性与综合性能最优 |
| 静态存在性预判 | 布隆过滤器 | 空间极致压缩,O(1) 查询 |
| 动态增删存在性预判 | 布谷鸟过滤器 | 支持安全删除,假阳性率可控 |
| 范围查询预判 | SuRF | 唯一支持范围查询的轻量过滤器 |
| 内存有序动态数据 | 跳表 | 无需重平衡,近似 O(log n) |
| 字符串前缀检索 | 基数树 | 压缩空间,树高度低 |
| 文本关键词检索 | 倒排索引 | 全文检索性能碾压传统索引 |
| AI 语义相似度检索 | 向量索引(HNSW / IVFFlat) | 突破关键词匹配限制 |
| 高频简单查询优化 | 索引包含列 | 消除回表 IO |
| 固定过滤条件优化 | 局部索引 | 索引体积缩小 |
选型核心原则:
- 树类索引:B+ 树仍是磁盘数据库点查询与范围查询的最优选择,稳定性和综合性能最优。
- 过滤器:布隆过滤器用于静态预判,布谷鸟过滤器用于动态增删预判,SuRF 用于范围预判。
- 内存索引:跳跃表适配内存有序动态数据,基数树适配字符串前缀检索。
- 检索场景:倒排索引用于文本关键词检索,向量索引用于 AI 语义相似度检索。
- 优化手段:局部索引与包含列索引可针对性优化特定业务查询性能。