倒排索引能实现高速检索,核心在于其内部精巧的数据结构设计,其中 FST 和位图 扮演了关键角色。它们各司其职,共同保证了在海量数据下既能快速定位,又能高效计算。
为了让你快速建立整体认知,下表清晰地对比了这两种数据结构的核心职责与特性。
| 特性 | FST | 位图 |
|---|---|---|
| 核心功能 | 快速定位关键词 | 高效进行集合运算 |
| 扮演角色 | 索引的索引,用于定位关键词在词典中的位置 | 文档列表的压缩与运算表示,用于处理文档ID集合 |
| 工作阶段 | 查询的第一站,决定"关键词在哪" | 查询的第二站,处理"哪些文档包含它" |
| 关键优势 | 极高的内存压缩率,能大幅降低内存占用 | 极快的位运算速度,适合多条件组合查询 |
🔍 FST:如何快速定位关键词
你可以把FST想象成一棵经过高度压缩的前缀树。它的核心使命是:给定一个关键词,能快速判断它是否存在,并找到其关联的元数据(如指向倒排列表的指针)。
-
构建与压缩 :FST的构建基于已排序的关键词列表。它通过共享前缀和后缀来压缩存储。例如,对于"cat"和"dog"等词,FST会构建一个图结构,其中每个节点代表一个字符状态,并通过共享共同的前缀(如"cat"和"can"共享"ca")来减少节点数量,从而大幅节省存储空间。
-
查找过程 :查找时,从根节点开始,根据输入关键词的每个字符依次进行状态转移。如果能够沿着路径到达一个终止状态,并且该状态输出目标值,则说明关键词存在。这个过程的时间复杂度是O(key_length),与整个词典的大小无关,因此速度极快。
🔢 位图:如何高效处理文档集合
当通过FST找到关键词后,下一步是获取包含该关键词的所有文档ID列表。位图是高效表示和操作这些文档ID集合的神器。
-
文档列表的位图表示:系统为每个文档分配一个唯一的ID。对于一个关键词,可以创建一个巨大的位数组,如果某个文档ID包含该关键词,则数组中对应该ID的比特位就被设置为1,否则为0。这样,一个文档集合就被压缩成了一个比特串。
-
高效的集合运算 :多条件查询(如"苹果 AND 手机")的本质是求两个文档集合的交集。位图的优势在于可以利用CPU的位指令快速完成运算。按位与 操作对应求交集,按位或操作对应求并集,速度远超遍历比较列表。
-
压缩优化 :直接使用位图在文档ID非常稀疏时会造成空间浪费。因此,业界广泛采用RoaringBitmap等压缩技术。它将整个ID空间分块,针对稀疏块使用更节省空间的存储方式,从而在高性能运算的同时保持了极高的压缩率。
🤝 协同工作流程
下图直观地展示了在一个多关键词查询中,FST和位图是如何协同工作的:
flowchart TD
A["用户查询:<br>关键词A AND 关键词B"] --> B["1. 分词<br>得到关键词A, 关键词B"]
B --> C{"2. 通过FST查找"}
C --> D["关键词A"]
C --> E["关键词B"]
D --> F["找到关键词A<br>对应的倒排列表<br>(位图形式)"]
E --> G["找到关键词B<br>对应的倒排列表<br>(位图形式)"]
F --> H{"3. 位图运算"}
G --> H
H --> I["对两个位图<br>进行按位与操作"]
I --> J["得到结果文档ID集合"]
J --> K["4. 返回最终搜索结果"]
💎 总结
总而言之,FST和位图是倒排索引高效实现的两个支柱。FST凭借其极高的压缩效率 ,解决了在海量词汇中快速定位关键词的难题;而位图则利用其天生的并行计算能力,解决了复杂查询条件下大规模文档集合的快速运算问题。
希望这些解释能帮助你透彻地理解它们的工作原理。如果你对某个特定细节或应用场景有更进一步的兴趣,我们可以继续深入探讨。