排序与深分页是什么
Elasticsearch 的常规分页用 from 与 size,但超过窗口上限会直接报错而不是变慢;翻深页的正确做法是游标分页:把上一页最后一条的排序值带回来作为起点,每次只取下一页。导出类场景再配合时间点视图保持一致性快照。理解这套机制,就不会在导出十万条日志时踩到窗口限制,也不会因为越翻越慢而拖垮集群。
基本信息
| 适用引擎 | Elasticsearch 7.x / 8.x |
|---|---|
| 普通分页上限 | 受 max_result_window 限制,默认 10000 |
| 游标分页 | search_after 配合稳定排序键 |
| 一致性视图 | PIT 或滚动查询,用于长时间导出 |
典型使用场景
- 控制台翻页:界面第 2 到第 5 页用 from 与 size 足够
- 批量导出:按时间倒序游标拉取,避免触发窗口限制
- 对账脚本:需要稳定顺序与完整覆盖时用游标逐批处理
- 深页查询:翻到第 100 页时改用游标而不是加大窗口
- 大范围导出:配合时间点视图避免新旧数据混在一起
分页写法
分页写法
# 普通分页:from 加 size,受 max_result_window 限制
GET /logs-app/_search {"from": 0, "size": 50, "sort": [{"@timestamp": "desc"}]}
# 游标分页:排序键必须稳定且唯一,时间戳加 _doc 兜底
GET /logs-app/_search
{"size": 100,
"sort": [{"@timestamp": "desc"}, {"_doc": "asc"}],
"search_after": [1750000000000, 42]}
# 批量导出建议:按时间倒序逐批拉取,记录每批末条排序值
# 结果条数少于 size 时表示已经翻到底,可以结束循环分页方式对照
| 方式 | 适用深度 | 注意事项 |
|---|---|---|
| from 加 size | 浅页,几百条以内 | 超过窗口上限直接报错 |
| search_after | 深页与批量导出 | 排序键必须唯一且稳定 |
| PIT | 需要一致性视图的导出 | 用完要显式释放 |
| 滚动查询 | 一次性大导出 | 占用资源较多,适合离线任务 |
排序键必须唯一:只按时间戳排序时同一毫秒内的多条文档顺序不稳定,翻页可能出现重复或漏行,典型做法是加 _doc 作为兜底排序键。
为分页排序的字段需要开启正排索引(doc_values),keyword 与 date 类型默认满足;对 text 字段排序会因缺少正排索引而失败。