八股文解析
Elasticsearch 为什么搜索快?倒排索引原理
一句话结论
ES 搜索快靠的是倒排索引(Inverted Index),它把“文档→词”的扫描问题变成“词→文档”的 O(1) 查找。
面试标准答法
1. 核心机制:倒排索引(Inverted Index)
正向索引(Forward Index) 是传统关系型数据库的存储方式:每行记录存一个文档 ID,查询时全表扫描匹配字段内容。数据量到百万级,全表扫描必然超时。
倒排索引 反向构建:先对每个文档做分词(Tokenizer + Analyzer),得到词条(Term)列表,然后建立 Term → 包含该 Term 的文档 ID 列表(Posting List) 的映射。
文档1: "Elasticsearch is fast"
文档2: "Elasticsearch uses inverted index"
倒排索引(简化):
"elasticsearch" → [doc1, doc2]
"fast" → [doc1]
"uses" → [doc2]
"inverted" → [doc2]
"index" → [doc2]查询 "elasticsearch" 时,直接从索引中取出 [doc1, doc2],无需扫描全部文档。
2. 加速细节:不只是倒排索引
倒排索引只是基础,ES 还叠加了以下机制,层层加速:
2.1 Term Dictionary + Term Index(FST)
- Term Dictionary:所有不重复词条的排序列表,用于定位某个 Term 在 Posting List 中的位置。
- Term Index:对 Term Dictionary 的前缀构建 FST(Finite State Transducer,有限状态转换器),常驻内存,将 Term 查找从二分查找 O(log N) 降到近似 O(1)。
FST 是 ES 搜索快的关键点之一:它把几十 GB 的词典压缩成几百 MB 的内存结构,同时保留前缀共享,支持模糊匹配和前缀查询。
2.2 Posting List 的压缩与跳表
- Frame of Reference(FOR):对文档 ID 做增量编码(Delta Encoding),再用 Bit Packing 压缩,减少存储和 I/O。
- Roaring Bitmap:当 Posting List 足够密集时,ES 自动切换为位图存储,利用 CPU 位运算加速交集/并集。
- 跳表(Skip List):Posting List 内部维护跳表指针,多 Term 求交集(如
must查询)时,跳过不匹配的文档,减少比较次数。
2.3 分段存储(Segment)与合并
- 每个 Segment 是一个独立的倒排索引,写入时先进内存 buffer,refresh 后生成 Segment。
- 查询时并行搜索所有 Segment,结果合并返回。
- 后台 Merge 线程定期合并小 Segment 为大 Segment,删除旧版本,保证查询效率不随 Segment 数量退化。
2.4 列式存储:Doc Values
- 排序、聚合、脚本计算需要读取字段原始值,ES 用 Doc Values(列式存储)替代倒排索引,避免对倒排索引做反查。
- 列式存储按列连续存放,压缩率高,读取时只需加载涉及的列,跳过无关数据。
3. 对比表格
| 维度 | 正向索引(MySQL InnoDB) | 倒排索引(Elasticsearch) |
|---|---|---|
| 数据结构 | B+ Tree | Term → Posting List + FST |
| 查询方式 | 索引扫描 + 回表 | Term 查找 + 位图/跳表合并 |
| 适合场景 | 等值查询、范围查询、事务 | 全文检索、模糊匹配、聚合分析 |
| 写入效率 | 高(原地更新) | 中(写缓冲 + 分段合并) |
| 存储开销 | 低 | 高(索引+字段副本) |
| 典型延迟 | 毫秒级(单行) / 秒级(全表) | 毫秒级(即使全量) |
常见追问
| 追问 | 要点 |
|---|---|
| 为什么 MySQL 不用倒排索引? | MySQL 主场景是等值/范围查询,B+ Tree 有序性天然支持;全文检索用倒排索引但实现弱(ngram 分词差)。ES 牺牲写入和事务,换取查询灵活性。 |
| ES 写入慢是为什么? | 写入要经过分词、构建倒排索引、写 translog、refresh 生成 Segment、定期 merge。每一步都有开销,但都是为查询快做铺垫。 |
| 为什么聚合慢? | 聚合走 Doc Values 列式存储,虽然比行式快,但需要遍历所有匹配文档的列值,计算量随数据量线性增长。 |
| 倒排索引能存数值吗? | 可以,但数值范围查询效率不如 B+ Tree。ES 对数值类型默认同时建倒排索引和 Doc Values,前者用于过滤,后者用于排序聚合。 |
面试回答模板(30 秒版)
延伸准备
- FST 原理:能画图解释 FST 如何共享前缀、如何用有限状态机表示词典,以及为什么比 HashMap 更省内存(前缀压缩 + 有序性支持范围查询)。
- Roaring Bitmap vs BitSet:说明 Roaring Bitmap 如何分桶存储(高 16 位分桶,低 16 位用数组或位图),以及为什么在稀疏/密集场景下都有优势。
- ES 与 Lucene 的关系:ES 底层是 Lucene 库,倒排索引、Segment、Doc Values 都是 Lucene 的能力,ES 只负责分布式协调、REST API 和集群管理。能讲清这层关系,说明你对 ES 架构有整体认知。
想系统备战大厂大模型/Agent 开发?NiceOffer 提供 SDE+LLM 双轨 1v1 陪跑,合同保底 40w 年薪,文末扫码咨询。