Elasticsearch 分页查询:从基础到深度分页的解决方案
在 Elasticsearch 中,分页查询是获取大量数据的常用操作,但不同分页方式的性能和适用场景差异显著。本文详细解析 from+size、scroll 和 search_after 三种分页方式的原理、用法及优缺点,帮助你根据业务场景选择最优方案。
基础分页:from+size(浅分页)
from+size 是最直观的分页方式,通过 from(跳过的条数)和 size(返回的条数)控制分页,适合数据量小、分页深度浅的场景(如前 10 页)。
用法示例
1 | # 基础语法 |
原理
- 当请求
from=100,size=20时,Elasticsearch 会向每个分片发送请求,要求每个分片返回from+size=120条数据。 - 协调节点收集所有分片的 120 条数据后,进行全局排序,再截取第 101~120 条作为结果返回。
优缺点
- 优点:实现简单,支持随机跳页(如直接从第 1 页跳到第 10 页)。
- 缺点:
- 深度分页(
from过大,如from=10000)时,每个分片需返回大量数据(10000+size),导致网络传输和排序开销激增,甚至触发内存限制(默认index.max_result_window=10000,超过会报错)。
- 深度分页(
游标分页:scroll(批量处理)
scroll 适用于批量处理全量数据(如数据导出、索引迁移),通过创建数据快照生成 scroll_id,后续基于游标获取下一页,不支持随机跳页。
用法示例
(1)初始化 scroll 并获取第一页
1 | # 生成 scroll_id,设置快照有效期为1分钟(scroll=1m) |
响应中会包含 _scroll_id(用于后续分页)和第一页数据。
(2)通过 scroll_id 获取下一页
1 | # 使用上一步返回的 scroll_id 继续查询 |
原理
scroll会在第一次查询时创建整个查询结果的快照(不包含后续新增 / 修改的数据),确保分页一致性。- 每次通过
scroll_id获取下一页时,直接从快照中读取数据,避免重复计算。
优缺点
- 优点:适合全量数据遍历,性能稳定(快照一次性生成,后续查询高效)。
- 缺点:
- 不支持随机跳页,只能顺序分页。
- 快照会占用大量内存和磁盘空间,且不会自动释放(需手动清理过期
scroll_id)。 - 数据非实时(快照生成后,新增 / 修改的数据不会被包含)。
清理 scroll 快照
使用完毕后,需手动删除 scroll_id 释放资源:
1 | DELETE _search/scroll |
实时分页:search_after(深分页)
search_after 基于上一页最后一条数据的排序值定位下一页,适合实时数据的深分页(如滚动加载列表),不支持随机跳页,但性能优异。
用法示例
(1)第一页查询(需指定排序字段)
1 | GET index/_search |
响应中每条数据会包含 sort 数组(如 ["1620000000000", "AuvQEIoBP0MzcZD49Ihs"]),记录排序字段的值。
(2)下一页查询(基于上一页最后一条的 sort 值)
1 | GET index/_search |
原理
search_after依赖排序字段,以上一页最后一条数据的排序值作为 “锚点”,直接从该位置向后查询,无需计算前面所有数据。- 必须指定唯一排序字段(通常结合业务字段 +
_id,确保排序值不重复,避免分页漏数据)。
优缺点
- 优点:
- 支持深分页(无
max_result_window限制),性能优异(无需全局排序)。 - 数据实时(每次查询都是基于当前最新数据)。
- 支持深分页(无
- 缺点:
- 不支持随机跳页,只能顺序分页。
- 依赖排序字段,需确保排序逻辑稳定(如字段类型、排序方向不变)。
三种分页方式对比与选择
| 分页方式 | 适用场景 | 支持跳页 | 实时性 | 性能(深分页) | 资源占用 |
|---|---|---|---|---|---|
| from+size | 浅分页(前 10~20 页) | 是 | 实时 | 差(随 from 增大下降) | 中 |
| scroll | 全量数据批量处理(如导出) | 否 | 非实时 | 好(快照一次性生成) | 高 |
| search_after | 深分页 + 实时数据(如滚动加载) | 否 | 实时 | 优(基于锚点查询) | 低 |
选择建议
- 前台分页(用户翻页):
- 浅分页(如前 10 页)用
from+size,实现简单。 - 深分页(如滚动加载更多)用
search_after,避免性能问题。
- 浅分页(如前 10 页)用
- 后台批量处理:
- 全量数据导出、索引迁移等场景用
scroll,确保数据一致性。
- 全量数据导出、索引迁移等场景用
- 特殊注意:
from+size避免from+size超过 10000(可修改index.max_result_window,但不推荐)。search_after必须设计稳定的排序字段(结合_id确保唯一性)