← 返回题目列表

Elasticsearch 的倒排索引是什么?为什么适合全文检索?

高频 中等 第 9 / 30 题 更新于 2026/07/28
Elasticsearch倒排索引分词全文检索

简化版

倒排索引就是从“词”反查“包含这个词的文档”。关系型数据库更像按行找数据,而 Elasticsearch 会先把文本分词、归一化,再建立词项到文档的映射,所以非常适合按关键词、相关性和条件组合做全文检索。

详细版

倒排索引可以理解为一本“词典 + 目录”:

  • 正排索引:从文档 id 找文档内容,例如 doc1 -> Java 面试题
  • 倒排索引:从词项找文档,例如 java -> doc1, doc8, doc20
  • 搜索时:用户输入查询词,Elasticsearch 经过 analyzer 分析后得到 token,再去倒排索引里找包含这些 token 的文档。
  • 排序时:不仅找“有没有”,还会结合词频、逆文档频率、字段长度等信息计算相关性分数。

例如有三篇文档:

文档title
1Java 集合面试题
2Elasticsearch 全文检索
3Java 全文搜索

粗略分词后可能得到:

词项文档
java1, 3
集合1
面试题1
elasticsearch2
全文2, 3
检索2
搜索3

当查询“Java 搜索”时,系统不需要扫描所有文档内容,而是直接查 java搜索 对应的文档列表,再合并、打分、排序。

面试回答时要补充两个点:

  1. 倒排索引适合搜索,但不等于所有查询都快;字段类型、分词器、查询方式、分片数量都会影响性能。
  2. Elasticsearch 底层基于 Lucene,倒排索引是核心能力,但 Elasticsearch 在它之上提供了分布式、REST API、聚合、集群管理等能力。

完整版教学

一、为什么普通数据库不擅长全文检索

如果在 MySQL 里对文本字段做:

SELECT * FROM article WHERE title LIKE '%Java%';

这种查询通常很难有效利用普通 B+ 树索引,因为 %Java% 前面有通配符,数据库不知道从索引树的哪个位置开始找,只能扫描大量数据。

全文检索的问题不是“按某个精确值找一行”,而是:

  • 文本里有没有某些词;
  • 这些词出现在哪些文档;
  • 出现次数多不多;
  • 出现在标题还是正文;
  • 哪篇文档更相关。

这类问题用“行到字段”的索引结构不够自然,用“词到文档”的倒排结构更合适。

二、倒排索引由哪些信息组成

简化理解,倒排索引主要包含三类信息:

  1. 词典:记录所有出现过的词项,比如 javasearchredis
  2. 倒排列表:记录每个词项出现在哪些文档中。
  3. 附加统计:记录词频、位置、偏移量等,用于短语查询、高亮和相关性评分。

例如:

java -> [doc1(freq=2), doc3(freq=1), doc8(freq=5)]
search -> [doc3(freq=1), doc9(freq=2)]

查询 java search 时,系统可以快速拿到两个倒排列表,然后根据查询逻辑做交集、并集或布尔组合。

三、分词器在倒排索引里扮演什么角色

倒排索引不是把原始句子直接塞进去,而是先做文本分析。一个 analyzer 通常包含:

  • character filter:字符预处理,例如去掉 HTML 标签;
  • tokenizer:切分词项,例如按空格、标点或语言规则切词;
  • token filter:词项归一化,例如小写化、停用词过滤、同义词扩展。

英文文本 Java Search Engine 可能被处理成:

java, search, engine

中文更需要注意,因为中文没有天然空格。中华人民共和国 如果分词策略不同,可能切成一个整体,也可能切成多个词。业务里搜索效果差,经常不是 Elasticsearch “不行”,而是分词器、同义词、字段设计没有配好。

四、倒排索引为什么能支持相关性排序

全文检索不只是返回匹配文档,还要把更相关的排在前面。Elasticsearch 默认相关性评分基于 Lucene 的相似度算法,现代版本默认使用 BM25。

粗略理解,评分会考虑:

  • 查询词在文档里出现得越多,通常越相关;
  • 越少见的词,区分度越高;
  • 字段越短,命中同一个词时通常越集中;
  • 不同字段可以设置不同权重,例如标题权重大于正文。

所以搜索“Java 集合”时,标题里完整出现“Java 集合”的文章,往往比正文角落偶然出现这些词的文章更靠前。

五、倒排索引的代价和使用边界

倒排索引让搜索更快,但也有成本:

  • 写入时要分词、建索引,所以写入链路比简单追加更重;
  • 字段越多、分词越复杂,索引体积越大;
  • 数据更新本质上接近“删除旧文档 + 写入新文档”,不是原地改倒排列表;
  • 需要根据业务选择 textkeyword、分词器、refresh 策略和分片策略。

因此 Elasticsearch 常用于搜索、日志检索、指标分析、复杂过滤和聚合,不适合替代强事务关系型数据库。

六、常见误区与追问

概念解决的问题例子
词典有哪些 termjavasearchbm25
倒排列表term 出现在哪些文档java -> doc1, doc3
词频/位置如何评分、短语匹配、高亮freq=3, positions=[2,8,19]
analyzer原始文本怎样变成 term小写、分词、停用词、同义词
doc1: Java search
doc2: Search engine

倒排后:
java   -> doc1
search -> doc1, doc2
engine -> doc2

记忆钩子:B+ 树像“按值找行”,倒排索引像“按词找文档”,全文检索的快就来自方向反过来了。

一个小推演:100 万篇文章里只有 2000 篇包含 StampedLock,查询这个词时直接读取对应倒排列表即可;如果用 %StampedLock% 扫正文,可能要检查 100 万篇文本。倒排索引把“运行时扫描”提前成“写入时建索引”,所以读快但写入和存储更重。

  • 误区:倒排索引只保存文档 id。 实际还会保存词频、位置、偏移量等信息,用于 BM25 评分、短语查询和高亮。
  • 误区:有倒排索引就一定能搜得准。 搜索质量强依赖 analyzer、同义词、字段权重、query 写法和业务排序。
  • 误区:Elasticsearch 适合替代所有数据库查询。 倒排索引擅长全文检索和分析,不代表强事务、复杂关联和精确更新也适合放到 ES。
  • 追问:为什么中文搜索更依赖分词器? 中文没有天然空格,切词粒度会直接影响 term 生成,进而影响召回和排序。
  • 追问:更新文档为什么成本高? Lucene segment 近似不可变,更新常表现为标记旧文档删除并写入新文档,后续再通过 merge 回收空间。
  • 追问:倒排索引和 BM25 有什么关系? BM25 需要词频、文档频率、字段长度等统计信息,这些信息正是围绕倒排索引维护和读取的。

七、加强记忆

记住“倒排索引 = 从词找文档”。面试中先讲普通数据库按行组织数据,全文检索需要按词定位文档;再讲分词、倒排列表、相关性评分;最后补一句边界:搜索强,不代表事务强,字段设计和分词策略会直接决定搜索效果。