详解 ES 的倒排索引机制
ES(Elasticsearch)的倒排索引(Inverted Index)是其实现高效全文检索的核心数据结构。
ES 的倒排索引是以“词”为中心,将词映射到文档集合,从而实现高效、可扩展的全文检索。
什么是倒排索引
倒排索引 = 从「词 → 文档」的映射
- 正排索引:
文档 → 包含哪些词 - 倒排索引:
词 → 出现在哪些文档中、出现了多少次、出现在哪些位置
👉 ES 实际上基于 Lucene,倒排索引是 Lucene 的核心能力。
倒排索引的基本结构
一个典型的倒排索引由三部分组成:
1️⃣ Term Dictionary(词典)
存储所有不重复的词(term)
hello
world
elasticsearchES 内部使用 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
index2️⃣ 规范化(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" }
}流程:
- 在词典中找到
index - 取出 posting list
- 返回对应文档
⚡ 非常快(O(log n))
2️⃣ Match Query(全文检索)
{
"match": { "content": "inverted index" }
}步骤:
- 查询文本分词
- 分别查两个 term 的 posting list
- 求交集
- 计算相关度(BM25)
3️⃣ Phrase Query(短语查询)
"inverted index"- 使用 positions
- 判断两个词是否相邻
倒排索引与相关度计算
ES 默认使用 BM25:
评分因素包括:
- TF(词频)
- IDF(逆文档频率)
- 文档长度归一化
公式核心思想:
词在当前文档中越重要,且越少见,得分越高
倒排索引的优缺点
✅ 优点
- 查询速度极快
- 非常适合全文搜索
- 支持短语、模糊、范围组合查询
❌ 缺点
- 写入成本高(需要分词 + 建索引)
- 占用较多磁盘空间
- 不适合高频更新(依赖 Segment Merge)
详解 ES 的倒排索引机制
https://liuyuhe666.github.io/2025/12/17/详解-ES-的倒排索引机制/