核心概念

倒排索引(Inverted Index) 是全文检索引擎的核心数据结构,它将文档中的每个词(Term)映射到包含该词的文档列表,实现了从词到文档的快速查找,与传统的文档到词的正向索引相反。

倒排索引的结构

1. 正排索引 vs 倒排索引

正排索引(Forward Index):文档 → 词

Doc1 → ["Java", "ElasticSearch", "搜索引擎"]
Doc2 → ["Java", "MySQL", "数据库"]
Doc3 → ["ElasticSearch", "分布式", "搜索"]

倒排索引(Inverted Index):词 → 文档

"Java"           → [Doc1, Doc2]
"ElasticSearch"  → [Doc1, Doc3]
"MySQL"          → [Doc2]
"搜索引擎"       → [Doc1]
"数据库"         → [Doc2]
"分布式"         → [Doc3]
"搜索"           → [Doc3]

2. 倒排索引的组成

倒排索引由两部分组成:

词典(Term Dictionary)

  • 存储所有不重复的词(Term)
  • 按字典序排序,支持快速查找
  • 常用数据结构:FST(Finite State Transducer)

倒排列表(Posting List)

  • 存储包含该词的文档 ID 列表
  • 每个条目包含:
    • 文档 ID(Doc ID)
    • 词频(TF,Term Frequency):词在文档中出现的次数
    • 位置信息(Position):词在文档中的位置,支持短语查询
    • 偏移量(Offset):词的起始和结束字符位置,支持高亮
Term: "ElasticSearch"
Posting List:
  - Doc1: TF=2, Positions=[5, 120], Offsets=[25-38, 560-573]
  - Doc3: TF=1, Positions=[0], Offsets=[0-13]

倒排索引的构建过程

1. 文档分词

// 原始文档
Doc1: "ElasticSearch 是一个强大的搜索引擎"
Doc2: "搜索引擎基于倒排索引实现"

// 分词后
Doc1: ["ElasticSearch", "是", "一个", "强大", "的", "搜索", "引擎"]
Doc2: ["搜索", "引擎", "基于", "倒排", "索引", "实现"]

2. 构建倒排索引

Term Dictionary:
"ElasticSearch" → [Doc1]
"是"            → [Doc1]
"一个"          → [Doc1]
"强大"          → [Doc1]
"搜索"          → [Doc1, Doc2]
"引擎"          → [Doc1, Doc2]
"基于"          → [Doc2]
"倒排"          → [Doc2]
"索引"          → [Doc2]
"实现"          → [Doc2]

3. 查询过程

// 查询 "搜索引擎"
Step 1: 分词  ["搜索", "引擎"]
Step 2: 查词典  "搜索"  [Doc1, Doc2]
                 "引擎"  [Doc1, Doc2]
Step 3: 求交集  [Doc1, Doc2]都包含这两个词
Step 4: 相关性评分TF-IDFBM25
Step 5: 返回排序后的结果

ElasticSearch 中的优化

1. FST(Finite State Transducer)

  • ES 使用 FST 存储词典,实现内存高效存储
  • FST 既能快速查找,又能节省内存(共享前缀)
例如:词典中有 "cat", "cats", "dog", "dogs"
传统存储:16 字节
FST 存储:通过共享前缀和后缀,大幅减少空间

2. Frame of Reference 编码

  • 倒排列表中的文档 ID 进行差值编码和压缩
  • 例如:[100, 105, 110] → [100, +5, +5]

3. Roaring Bitmap

  • 对倒排列表进行位图压缩
  • 适合包含大量文档 ID 的场景

4. 跳表(Skip List)

  • 在倒排列表中使用跳表,加速多词求交集操作
  • 避免遍历整个列表

实际示例

电商商品搜索

// 假设有以下商品文档
{
  "id": 1,
  "name": "Apple iPhone 15 Pro Max",
  "description": "最新款苹果手机,搭载 A17 芯片"
}
{
  "id": 2,
  "name": "Apple MacBook Pro",
  "description": "专业级苹果笔记本电脑"
}
{
  "id": 3,
  "name": "华为 Mate 60 Pro",
  "description": "旗舰手机,5G 性能强劲"
}

// 构建倒排索引(部分)
"apple"      [1, 2]
"iphone"     [1]
"pro"        [1, 2, 3]
"macbook"    [2]
"手机"       [1, 3]
"苹果"       [1, 2]
"华为"       [3]

// 搜索 "苹果 Pro"
Step 1: 分词  ["苹果", "pro"]
Step 2: 查倒排索引
        "苹果"  [1, 2]
        "pro"   [1, 2, 3]
Step 3: 求交集  [1, 2]
Step 4: 评分排序考虑词频文档长度字段权重等
Result: [1, 2]iPhone 15 Pro Max  MacBook Pro

倒排索引的优势

1. 快速全文检索

  • 直接通过词定位文档,时间复杂度 O(1)
  • 避免全表扫描

2. 支持复杂查询

  • 词组查询(Phrase Query):利用位置信息
  • 近似查询(Proximity Query):词的距离约束
  • 前缀查询(Prefix Query):利用词典的有序性

3. 相关性评分

  • 基于 TF-IDF 或 BM25 算法
  • 考虑词频、逆文档频率、文档长度等因素

性能考量

1. 写入性能

  • 构建倒排索引需要分词、排序,写入有一定延迟
  • ES 采用 Segment 机制,批量构建索引

2. 磁盘占用

  • 倒排索引需要额外存储空间
  • ES 通过压缩算法(FST、FOR、Roaring Bitmap)优化

3. 更新策略

  • 倒排索引不支持原地更新(Immutable)
  • ES 采用标记删除 + 后台合并策略

总结

倒排索引是搜索引擎的基石,它通过词 → 文档的映射,实现了高效的全文检索。ElasticSearch 基于 Lucene 的倒排索引,并通过 FST、压缩算法、跳表等优化,在空间和时间上取得平衡。

面试要点

  • 清晰解释倒排索引的概念(词 → 文档)
  • 说明词典和倒排列表的组成
  • 举例说明查询过程(分词 → 查词典 → 求交集 → 评分)
  • 可提及 FST、压缩算法等优化手段