Elasticsearch深度分页问题完整解析

Elasticsearch 深度分页完整详解

一、什么是深度分页问题

ES原生分页使用 from + size 参数:from代表跳过多少条,size代表本次返回多少条。

示例:from=9990,size=10,代表跳过9990条,取后面10条,也就是第1000页。

ES是分布式架构,索引数据会拆分成多个分片存储from+size在深分页时底层执行流程:

  1. 协调节点把查询请求转发给索引每一个分片
  2. 每个分片各自查询出 from + size 条文档,返回给协调节点; ⚠️重点:不是只查10条,每个分片都要拿到前(from+size)条数据 。比如索引有5个分片,查第10000页,每个分片都要返回10010条文档,协调节点一共收到 5*10010 条数据。
  3. 协调节点把所有分片返回的数据全部收集到内存,做全局排序
  4. 在内存中舍弃前面from条记录,仅仅留下size条返回给客户端。

带来三大负面影响

  1. 高内存消耗:协调节点需要把大量文档加载到堆内存做排序。页码越深,内存存放的数据越多,堆内存占用急剧上涨。
  2. 查询性能低下:分片检索、网络传输、协调节点全局排序都要消耗CPU,页码越深响应时间越长。
  3. 集群稳定性风险:高并发深度分页请求,会把集群CPU、内存打满,严重直接节点OOM崩溃。

默认限制 index.max_result_window=10000

ES做保护:from + size > 10000,直接抛出异常拒绝查询。

❗千万不要直接调大这个参数! 调参数只是把报错屏蔽,底层分片查询、内存排序的资源消耗一点不会减少,只是把风险隐藏,线上极易引发OOM,生产环境禁止修改。
底层本质:ES倒排索引擅长条件过滤检索;但是跳过大批量文档,没有捷径,必须读取数据、全局排序,资源开销巨大。

二、主流解决方案详解

1. Scroll API(滚动游标)

Scroll 的核心是索引快照 。第一次执行scroll查询的时候,生成一份索引当时的静态快照,产出scroll_id。这个快照固定住查询那一刻索引的数据视图。后续每次请求带上scroll_id,就持续从快照位置读取下一批数据。

复制代码
response = es.scroll(
    scroll='2m',       # 快照存活时间,2分钟内保留这份视图
    scroll_id=scroll_id 
)

✅优点:适合大批量遍历,性能稳定,不受10000条限制。

❌缺点:

  1. 快照会占用集群内存、磁盘资源;到达scroll超时时间才会释放,如果程序异常中断,快照不会主动回收,持续占用资源。
  2. 读取静态快照数据:在scroll会话期间,索引新增、修改、删除的文档完全看不到,拿不到实时最新数据。
  3. 没有分页概念,只适合全量拉取,官方明确不推荐用于前端业务分页。

✅适用场景:数据导出、索引重建迁移、全量数据同步,后台一次性批量任务,不用于用户端业务。

2. search_after(排序游标分页)

search_after 没有页码、没有from参数 。原理:拿上一页最后一条文档的排序字段的值作为游标,告诉ES从这个位置往后读取数据。

复制代码
{
  "search_after": [1463538857, "log1234"],
  "size":10,
  "sort": [{"create_time":"desc"},{"_id":"asc"}]
}

⚠️非常关键:sort排序字段组合必须全局唯一 。 如果sort字段组合存在重复值,ES无法精准定位断点,会出现文档重复读取、漏读。 实践技巧:业务排序字段 + _id(文档唯一id)组合排序,保证组合一定全局唯一。

原生search_after的致命缺陷

单纯使用search_after没有快照保护 。 ES底层会定期执行段合并(segment merge),同时业务有新增、修改、删除文档,会改变文档排序顺序。分页过程中索引发生变化,文档顺序偏移,就会出现漏数据、重复读到同一条数据

ES7最佳实践:search_after + PIT(Point‑in‑Time 时间点快照)

PIT,时间点快照,专门解决search_after的数据错乱问题。 完整流程:

  1. 先创建PIT快照,设置keep_alive存活时长,拿到pit.id;创建快照那一刻固定索引视图;
  2. 每一次翻页请求,都携带同一个pit.id,整个分页会话都读取这份快照里面的数据;业务新增修改删除不会影响本次分页结果,保证分页一致性;
  3. 分页全部完成之后,必须手动调用接口删除PIT,释放资源。如果不删除,PIT快照会一直占用内存,造成内存泄漏。

✅优点:突破10000条限制,性能稳定,适合线上用户业务。 ❌缺点:只能向后顺序翻页,不能随机跳转到指定页码,适合下拉加载更多的信息流场景,不能实现"跳转到第500页"。

对比Scroll:PIT是会话级轻量快照;Scroll偏向大批量离线导出;线上业务滚动分页优先search_after+PIT

3. 业务层限制分页深度

不改动ES查询逻辑,从产品交互层面规避深度分页请求。 示例:

  1. UI限制用户最多只能查看前100页;超过最大页码提示"请增加筛选条件缩小范围";
  2. 抛弃数字页码组件,改用下拉加载更多交互。

✅优点:改动成本最低,从源头杜绝深度分页请求,减轻集群压力。 ❌缺点:产品需要做出妥协,无法满足直接跳转到大页码的需求。


三、各分页方案对比

方案 支持深度分页 支持随机跳页 数据一致性 适用场景 主要缺点
from + size 实时最新数据 浅分页小列表 深分页内存暴涨,默认上限10000条
Scroll API 快照静态数据 全量导出、索引迁移 占用集群资源,看不到实时数据,不适合业务搜索
search_after(无PIT) 无快照,容易错乱 几乎不会变更的静态数据列表 索引增删改、段合并会漏、重复数据
search_after + PIT 快照保证会话内一致 业务信息流、全文检索滚动分页 PIT占用资源,不支持跳页

四、生产环境选型总结

  1. 用户端全文检索、APP下拉滚动信息流 :优先使用 search_after + PIT;会话结束务必删除PIT,防止内存泄漏。
  2. 后台大批量导出数据、索引迁移同步:使用Scroll API。
  3. 后台管理系统,必须支持页码跳转:不要在ES做深度分页,把查询下沉到MySQL做分页处理。
  4. 产品允许的前提下,优先业务层限制最大页码,从根源规避深分页。

补充:ES深度分页 VS MySQL深度分页(面试高频对照)

  1. MySQL limit offset,size:offset很大,数据库需要扫描offset条记录然后丢弃; 优化手段:子查询书签分页、keyset游标分页;MySQL没有快照机制,分页过程中数据发生删除新增,会出现分页错乱。
  2. MySQL keyset游标分页 ≈ ES search_after;
  3. ES额外提供PIT快照能力,可以在分页会话内固定数据视图,规避数据变更带来的错乱,MySQL原生没有这个能力。

区别重点:MySQL游标分页读取的是实时数据;ES搭配PIT可以读取快照视图,会话内屏蔽数据变更。

面试口述速记

ES深度分页问题来源于from+size分布式分页机制。查询深页码时,每个分片都要查询from+size条数据,全部汇总到协调节点内存做全局排序,内存CPU消耗巨大,容易OOM,ES默认限制总和不能超过10000,不建议调大参数。 Scroll API依靠scroll_id快照,适合离线全量导出,看不到实时数据,不适合线上业务。 search_after拿上一页排序结果作为游标,没有页码;单独使用,索引变更会造成分页错乱。ES7推荐搭配PIT时间点快照,固定会话的数据视图保证一致性,用完手动释放PIT资源;但只能顺序向后翻页,不能随机跳页。 还可以业务层限制最大页码。后台需要跳页码的场景,把查询交给MySQL处理。

面试拓展追问

Q:PIT和Scroll快照有什么区别? A:

  1. Scroll面向大批量全量导出,数据量可以很大;PIT偏向业务分页,轻量级会话快照。
  2. Scroll使用scroll_id;PIT使用pit.id
  3. Scroll快照会保存完整的读取进度;PIT只固定索引视图,读取进度交给search_after游标维护。
  4. Scroll超时自动释放;PIT建议业务代码手动删除,避免内存泄漏。

Q:为什么sort字段必须全局唯一? A:如果sort字段存在多条文档排序值完全一样,ES无法精准定位search_after断点,无法区分两条数据,就会出现重复读取或者跳过文档。业务通常用业务排序字段拼接_id保证组合唯一。

Q:那PIT里面的数据是旧的,用户看不到新数据怎么办? A:PIT是单页翻页会话内部保持一致性;用户重新刷新页面,会创建全新PIT快照,读取最新索引数据。只有同一次下拉翻页会话期间,才使用旧快照视图,不会影响刷新首页。

相关推荐
小柯南敲键盘1 小时前
跨境电商批量图片翻译与视频字幕翻译,就用跨马AI工具
大数据·人工智能·python·音视频
GlobalInfo1 小时前
正文回答“是什么”,附录回答“为什么是这样”
大数据·人工智能
数字孪生视频孪生1 小时前
空间智能技术|跨镜轨迹全域可溯,无感定位无扰赋能落地
大数据·运维·人工智能·重构·架构
深海鱼肝油ya1 小时前
向量数据库Elasticsearch(一)
人工智能·elasticsearch·向量数据库·es数据库增加索引·es数据库相似度查询·knn查询
Raas1001 小时前
AI网关和LLM网关区别?MAI Gateway(魔芋企业级AI网关)企业级方案对比指南
大数据·人工智能·gateway·mai gateway·企业级产品
imbackneverdie1 小时前
国内有哪些比较全面的生物医学相关数据库?
大数据·数据库·人工智能·ai·信息可视化·aigc·科研
南讯股份Nascent1 小时前
2026年CRM技术选型观察:当“数据打通“成为第一需求,电商CRM的架构价值在哪里
java·大数据·用户运营
海浪仙人掌2 小时前
财务年报怎么填报?财务年报填报有哪些流程?
大数据
Sophnet云平台2 小时前
从 IT 自嗨到业务可用,制造企业 AI 平台的落地实践
大数据·人工智能·llm·制造·token·云平台