Java 面试题

Elasticsearch倒排索引:全文检索怎么做快

ES怎么把"百万文档搜一个词"做快?

为什么面试官会问这道题

中间件/搜索相关岗常见。懂倒排原理是"使用者"和"设计者"的分水岭。

如何回答

  1. 1

    建索引:分析器分词、归一化(小写、词干、停用词),再按term写posting list:term→按docId有序的(docId, position)列表。

  2. 2

    查询:term查索引(hash/btree),取posting list;多term AND求交、OR求并。

  3. 3

    打分:默认BM25——term在doc中频率、逆文档频率、长度归一化。越高越相关。

  4. 4

    段:Lucene写不可变segment,定期merge。删除是墓碑;更新=删+插。

  5. 5

    分片:索引按hash(_id)切成shard,每shard是Lucene索引。查询fan out到所有shard、协调节点合并。

参考回答示例

索引时ES把文本过分析器(分词→小写→词干→停用词→可能还有ngram),按token写posting list:term→(docId, 位置)列表。查询时token到索引里找(内部是FST+块树快前缀),posting AND求交或OR求并,候选按BM25打分——基本就是TF×IDF加长度归一化。这就是搜一个词O(log 词表+|结果|)不是O(|文档|)的原因。Lucene写不可变segment定期merge——删除是墓碑、更新=删+插。分片按doc id hash;查询fan out、协调节点合并打分结果。ES适合全文相关性和聚合,对高写事务弱(最终一致、单写因segment flush慢)。

实用技巧

  • 分析器选型决定质量——中文用IK或jieba,英文默认够。

  • 别深分页(from+size>1万)——用search_after游标。

  • 即答侠把"分析器→posting list→BM25"画成一张图——白板快。

常见问题

ES vs Postgres全文检索?

ES大规模、相关性调优、聚合更强。Postgres tsvector对小语料够,还省一套存储。

ES怎么更新文档?

老的打删除、新的作为新doc写入。实际空间在segment merge时才回收。

面试时担心忘词?即答侠实时助你

即答侠 AI 实时监听面试对话,自动识别问题并即时生成回答建议——无感辅助,让你从容应对每一道题。

免费试用即答侠