Elasticsearch 八股题库

这份题库重点不是“会不会调几个 DSL”,而是让你能把 Elasticsearch 讲成:

  • 为什么适合全文检索
  • 为什么不适合做主事务库
  • 倒排索引到底快在哪里
  • 分片、副本、refresh、merge 这些原理和工程问题怎么串起来

一、Elasticsearch 面试里你的最佳定位

你最稳的说法是:

我对 Elasticsearch 的理解,不是停留在建索引和写 DSL,而是知道它为什么适合承接搜索和检索型查询,也知道它和 MySQL 的职责边界,以及索引构建、分片、副本、刷新和数据同步这些治理问题。


二、高频题

1. Elasticsearch 为什么搜索快

标准回答

核心原因是倒排索引。 它不是按“文档 -> 包含哪些词”去查,而是按“词 -> 出现在哪些文档”去组织数据。

你可以补的点

  • 全文检索本质上是先分词
  • 每个 term 都维护 posting list
  • 查关键词时直接命中对应 term 的倒排链
  • 不需要像数据库 like '%xx%' 那样大量扫数据

面试更稳的说法

ES 快的核心不是某条 DSL 很高级,而是底层倒排索引把查找路径提前组织好了。


2. 什么是倒排索引

标准回答

倒排索引是按 term 建索引,记录每个 term 出现在哪些文档中。

简单例子

有三篇文档:

  • 文档 1:apple phone
  • 文档 2:apple watch
  • 文档 3:android phone

倒排索引会更像:

  • apple -> [1, 2]
  • phone -> [1, 3]
  • watch -> [2]
  • android -> [3]

所以搜 apple 时,直接能拿到文档 1 和文档 2。


3. Elasticsearch 和 MySQL 的核心区别是什么

标准回答

  • MySQL 更适合事务型主数据
  • Elasticsearch 更适合全文检索、复杂搜索和检索型聚合

面试更稳的说法

MySQL 的核心能力是事务、一致性和主状态;ES 的核心能力是搜索、过滤、排序和检索型查询。

项目里怎么讲

像商品搜索、批量导入后的检索、后台多条件筛选、搜索推荐这类场景,我会优先考虑 ES;但订单、支付、退款、订阅这些主状态一定还是回 MySQL。


4. 为什么说 ES 不适合做主库

标准回答

因为它不是为强事务、强一致主状态设计的。

你可以补的点

  • 默认更偏近实时而不是强实时
  • 主状态更新链路通常没有 MySQL 那么稳
  • 写入、刷新、分片、副本同步都更偏搜索引擎思路
  • 适合“查得快”,不适合“拿来做唯一真实状态”

面试更稳的说法

ES 非常适合查,但不应该成为订单、支付、退款这种业务主状态的唯一事实来源。


5. text 和 keyword 有什么区别

标准回答

  • text:会分词,适合全文检索
  • keyword:不分词,适合精确匹配、聚合、排序、过滤

例子

字段 name = "Apple Watch Ultra"

  • text 适合搜 apple
  • keyword 适合精确过滤整个字符串

面试更稳的说法

很多字段都应该同时建:

  • 一个 text 负责搜索
  • 一个 keyword 子字段负责过滤和排序

6. 分词器 analyzer 是干什么的

标准回答

分词器负责把文本拆成一个个 term,并决定:

  • 怎么切词
  • 是否转小写
  • 是否去停用词
  • 是否做同义词处理

面试更稳的说法

ES 搜索效果很大程度上不只是 DSL,而是 analyzer 设计得对不对。 搜索不准,很多时候根因是分词和 mapping 设计有问题。


7. shard 和 replica 是什么

标准回答

  • shard:分片,把一个索引拆成多个数据片段
  • replica:副本,复制主分片的数据,用于高可用和读扩展

面试更稳的说法

分片解决的是容量和并行问题,副本解决的是可用性和读能力问题。

注意点

  • 分片不是越多越好
  • 分片太多会带来管理、内存和查询协调成本

8. refresh、flush、merge 分别是什么

标准回答

  • refresh:让新写入的数据对搜索可见
  • flush:把内存中的数据和事务日志状态更稳定地落盘
  • merge:把多个小 segment 合并,减少碎片和查询开销

面试更稳的理解

这三个动作分别更偏:

  • 搜索可见性
  • 持久化阶段
  • 长期查询性能和索引整理

你不能把 refresh 理解成“已经彻底安全落盘”,它更偏近实时搜索可见。


9. 为什么说 ES 是近实时搜索

标准回答

因为文档写入后,不一定立刻就能被搜索到,通常要等 refresh 之后才能被检索命中。

面试更稳的说法

ES 更像“很快可查”,但不是数据库事务那种提交即强一致可见。


10. 查询流程大概是怎样的

标准回答

一次搜索大致会经历:

  1. 协调节点接收请求
  2. 把请求分发到相关分片
  3. 各分片本地执行 query
  4. 汇总排序
  5. 再 fetch 文档详情
  6. 返回最终结果

面试更稳的说法

ES 搜索往往不只是“查一个点”,而是多分片并行查询后再统一归并结果。


11. ES 写入流程大概是怎样的

标准回答

简化理解可以是:

  1. 文档写到主分片
  2. 写入内存缓冲和 translog
  3. 同步到副本分片
  4. refresh 后对搜索可见

面试更稳的说法

写入成功不等于立刻搜索可见,这就是为什么 ES 更偏近实时。


12. 搜索慢一般怎么排

标准回答

常见排查方向:

  • 查询 DSL 是否太复杂
  • 分片数是否过多
  • mapping 是否合理
  • 是否排序 / 聚合过重
  • 是否命中过滤缓存
  • 是否有深分页

你可以补的点

  • 看是不是 text / keyword 设计错误
  • 看是不是一边全文检索一边大量聚合
  • 看是不是深分页 from + size 太大
  • 看是不是热点索引或 segment 太碎

面试更稳的说法

ES 慢很多时候不是单点问题,而是 mapping、查询 DSL、分片设计和数据规模一起叠加出来的。


13. 深分页为什么慢

标准回答

因为 from + size 很大时,ES 需要先取出前面大量结果再丢弃,成本很高。

常见优化

  • search_after
  • scroll
  • 限制最大分页深度
  • 改交互方式,不让用户无限翻页

更完整一点怎么讲

1. 为什么 from + size 在 ES 里尤其贵

因为 ES 通常不是一台机器查完就结束,而是多分片并行查询。

当你查一个很靠后的页时,常见过程是:

  • 每个 shard 先找出自己前 from + size 条候选
  • 协调节点再把所有 shard 的候选结果做全局归并排序
  • 最后前面的 from 大量结果被直接丢掉

所以深分页真正贵的不是“最后只返回 10 条”,而是:

  • shard 端要维护更大的候选集合
  • 协调节点要 merge 更多结果
  • 排序、内存和 CPU 压力都会上升

2. 为什么默认只让你翻到 10000 条左右

这不是随便拍脑袋的限制,而是为了保护集群。

ES 默认会用:

  • index.max_result_window = 10000

去限制 from + size 的深度,防止某个深分页请求把整条搜索链路拖得很重。

3. search_after 是什么

search_after 可以理解成“基于上一页最后一条结果的游标分页”。

它不是每次都从第 1 页重新跳过前面几万条,而是:

  • 先拿第一页
  • 记住最后一条文档的 sort 值
  • 下一页从这个 sort 值之后继续查

所以它更像:

  • 顺着结果继续往后翻

而不是:

  • 每次都重算前面所有页再丢掉

4. search_after 适合什么,不适合什么

适合
  • “下一页”
  • “加载更多”
  • 无限滚动
不适合
  • 随意跳到第 378 页
  • query 和 sort 经常变化

因为它依赖:

  • 相同的 query
  • 相同的 sort
  • 上一页最后一条的排序值

5. 为什么经常说 search_after 最好配合 PIT

如果翻页过程中索引发生 refresh 或文档变化,结果顺序可能漂。

这时候会出现:

  • 重复
  • 漏数据
  • 页与页之间不稳定

PIT,也就是 point in time,可以理解成:

  • 在这次分页过程中固定一个索引视图

所以更稳的组合通常是:

  • search_after + PIT

6. scroll 是什么,为什么不推荐拿它做前台深分页

scroll 更像“批量扫描 / 离线导出 / 重建索引”的工具。

适合:

  • 全量导出
  • 批处理
  • 后台任务

不适合:

  • 用户前台实时翻页
  • 搜索结果页一页页点下去

因为 scroll 会维护服务端上下文,它更偏“遍历数据”,不是“交互式分页”。

7. 为什么“限制最大分页深度”本身也是优化

很多时候真正的问题不是 ES 不够快,而是产品交互不适合搜索系统。

比如:

  • 让用户跳到第 500 页
  • 在几十万结果里无限翻页

这类需求本身就不太适合搜索产品。

更合理的做法通常是:

  • 只保留浅分页
  • 改成“加载更多”
  • 强化筛选条件
  • 导出需求走异步导出

一段更像做过项目的回答

ES 深分页慢,不只是因为 from 很大,而是因为它是多分片查询。每个 shard 都要先拿出前 from+size 条候选,再由协调节点做全局归并和排序,所以越往后,内存和 CPU 成本越高。我的做法通常是:普通浅分页继续用 from+size;连续翻页用 search_after;如果要保证翻页期间结果稳定,就配 PIT;全量导出走 scroll;同时限制最大分页深度,不让用户无限翻页。


14. ES 和数据库同步一般怎么做

标准回答

常见做法:

  • 业务写 MySQL
  • 通过 MQ / Canal / binlog / 异步任务同步到 ES

面试更稳的说法

我一般会让 MySQL 做主状态,ES 做查询镜像,通过异步链路同步,接受短暂延迟,但不让 ES 反过来定义主状态。


15. 项目里怎么讲 ES 更自然

你可以说:

我项目里对 ES 的使用重点不是“会不会搭”,而是把它放在正确的位置。像搜索、筛选、批量导入后的检索、后台复杂查询,ES 很适合;但订单、支付、退款、订阅这些强状态链路,主事实仍然要在 MySQL。


三、你最该主动讲的 ES 项目化理解

1. ES 适合放什么

  • 商品 / 内容搜索
  • 多条件检索
  • 后台复杂筛选
  • 导入后快速查询

2. ES 不适合放什么

  • 支付主状态
  • 订单主状态
  • 退款主状态
  • 强事务核心数据

3. ES 的核心价值

不是“什么都能存”,而是:

  • 全文检索
  • 检索性能
  • 搜索排序
  • 过滤聚合

四、常见追问

追问 1:为什么不是所有查询都交给 ES

可以答:

因为 ES 的强项是搜索和检索,不是主状态事务。不是所有查询慢都应该甩给 ES,要先看它是不是搜索问题。

追问 2:ES 和 ClickHouse 有什么区别

可以答:

ES 更偏搜索和检索型查询,ClickHouse 更偏分析型聚合。一个更像搜索引擎,一个更像分析数据库。

追问 3:ES 数据不一致怎么办

可以答:

先接受它作为查询镜像的最终一致性定位,再通过 MQ、补偿任务、重建索引和对账机制把同步链路做稳。


五、你复习 ES 最该背的 10 个点

  1. 倒排索引
  2. 为什么搜索快
  3. text / keyword
  4. analyzer / 分词
  5. shard / replica
  6. refresh / flush / merge
  7. 近实时搜索
  8. 查询流程
  9. 深分页
  10. MySQL 和 ES 的职责边界