详解 ES 的倒排索引机制

ES(Elasticsearch)的倒排索引(Inverted Index)是其实现高效全文检索的核心数据结构。

ES 的倒排索引是以“词”为中心,将词映射到文档集合,从而实现高效、可扩展的全文检索。

什么是倒排索引

倒排索引 = 从「词 → 文档」的映射

  • 正排索引
    文档 → 包含哪些词
  • 倒排索引
    词 → 出现在哪些文档中、出现了多少次、出现在哪些位置

👉 ES 实际上基于 Lucene,倒排索引是 Lucene 的核心能力。

倒排索引的基本结构

一个典型的倒排索引由三部分组成:

1️⃣ Term Dictionary(词典)

存储所有不重复的词(term)

hello
world
elasticsearch

ES 内部使用 FST(Finite State Transducer) 来压缩存储,既省内存又支持快速查找。

2️⃣ Posting List(倒排列表)

每个 term 对应一个 posting list,记录它出现过的文档信息:

term: "hello"
posting list:
  docId=1, tf=2, positions=[3, 7]
  docId=4, tf=1, positions=[1]

包含信息:

  • docId:文档 ID
  • tf(term frequency):词频
  • positions:词在文档中的位置(用于短语查询)

3️⃣ Skip List / 压缩结构

  • 用于快速跳跃文档
  • 使用位压缩、增量编码等方式降低存储成本

ES 中倒排索引的构建流程

以一条文档为例:

{
  "title": "Elasticsearch is fast",
  "content": "Elasticsearch uses inverted index"
}

1️⃣ 分词(Analysis)

通过 Analyzer 处理文本:

  • character filter
  • tokenizer
  • token filter

结果可能是:

elasticsearch
is
fast
uses
inverted
index

2️⃣ 规范化(Normalization)

  • 小写
  • 去停用词
  • 词干化(running → run)

3️⃣ 建立倒排关系

elasticsearch → doc1 (pos=1)
fast           → doc1 (pos=3)
inverted       → doc1 (pos=6)

4️⃣ 写入 Segment

  • 倒排索引是不可变的
  • 新文档先写入新 Segment
  • 后台会做 Segment Merge

查询时如何利用倒排索引

1️⃣ Term Query(精确匹配)

{
  "term": { "content": "index" }
}

流程:

  1. 在词典中找到 index
  2. 取出 posting list
  3. 返回对应文档

⚡ 非常快(O(log n))

2️⃣ Match Query(全文检索)

{
  "match": { "content": "inverted index" }
}

步骤:

  1. 查询文本分词
  2. 分别查两个 term 的 posting list
  3. 求交集
  4. 计算相关度(BM25)

3️⃣ Phrase Query(短语查询)

"inverted index"
  • 使用 positions
  • 判断两个词是否相邻

倒排索引与相关度计算

ES 默认使用 BM25

评分因素包括:

  • TF(词频)
  • IDF(逆文档频率)
  • 文档长度归一化

公式核心思想:

词在当前文档中越重要,且越少见,得分越高

倒排索引的优缺点

✅ 优点

  • 查询速度极快
  • 非常适合全文搜索
  • 支持短语、模糊、范围组合查询

❌ 缺点

  • 写入成本高(需要分词 + 建索引)
  • 占用较多磁盘空间
  • 不适合高频更新(依赖 Segment Merge)

详解 ES 的倒排索引机制
https://liuyuhe666.github.io/2025/12/17/详解-ES-的倒排索引机制/
作者
Liu Yuhe
发布于
2025年12月17日
许可协议