ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

ES深度分页解决方案:性能对比与适用场景分析

2026/9/13 4:08:31 拓冰建站 浏览量
ES深度分页解决方案:性能对比与适用场景分析 ES深度分页解决方案性能对比与适用场景分析1. 引言在 Elasticsearch 中分页是常见的查询需求。然而当涉及深度分页即获取靠后的数据页时传统的分页方式会遇到严重的性能问题。随着数据量的增加深度分页会导致集群负载显著增加甚至可能影响整个集群的稳定性。本文将详细对比四种分页方案传统分页、Scroll、Search After 和 PIT分析它们的性能特点和适用场景帮助开发者根据实际需求选择最适合的分页策略。2. 传统分页及其局限性Elasticsearch 的传统分页使用from和size参数其中from表示跳过的文档数size表示每页返回的文档数。例如要获取第3页每页10条数据的查询如下GET /your_index/_search { query: { match_all: {} }, from: 20, size: 10 }性能问题当from size的值很大时ES 需要遍历大量文档导致内存消耗和查询时间显著增加ES 需要排序并获取前from size个文档然后丢弃前from个文档这一过程被称为 深度分页问题在大数据量场景下可能导致集群性能下降甚至触发 too many clauses 错误结论传统分页仅适用于浅分页前几页对于深度分页场景表现不佳应避免在生产环境中使用。3. 深度分页方案详解3.1 Scroll 方案Scroll 方案通过创建游标来遍历整个索引类似于数据库中的游标查询。它适合大数据量的全量数据导出场景。POST /your_index/_search?scroll1m { size: 100, query: { match_all: {} } }获取后续数据POST /_search/scroll { scroll: 1m, scroll_id: DXF1ZXJ5QW5kRmV0Y2gBAAAAAAABFZYWlkZAA1YmJjMWU3Zj... }优点能够遍历整个索引不受深度分页限制适合全量数据导出和批量处理场景缺点游标会占用大量内存不能实时获取新索引的数据快照数据实现复杂需要手动管理游标生命周期不支持实时更新数据3.2 Search After 方案Search After 方案基于上一页的最后一条记录的排序值进行分页避免了深度分页的性能问题。GET /your_index/_search { query: { match_all: {} }, size: 10, sort: [ { timestamp: asc }, { _id: asc } ] }获取下一页数据时使用上一页最后一条记录的排序值GET /your_index/_search { query: { match_all: {} }, size: 10, sort: [ { timestamp: asc }, { _id: asc } ], search_after: [1625097600000, 6Yd5eHQ] }优点不受深度分页限制性能稳定实时数据查询能够获取最新数据实现相对简单缺点需要稳定的排序字段且必须包含唯一值在排序数据发生变化时可能导致数据重复或缺失不适合需要排序字段频繁更新的场景3.3 PIT (Point in Time) 方案PIT 是 ES 7.10 引入的特性它创建了一个数据的时间点视图结合 Search After 实现深度分页。首先创建 PITPOST /your_index/_pit?keep_alive1m { body: {} }然后使用 PIT 进行搜索POST /_search { size: 10, query: { match_all: {} }, pit: { id: your_pit_id, keep_alive: 1m }, sort: [ { timestamp: asc }, { _id: asc } ] }获取下一页数据POST /_search { size: 10, query: { match_all : {} }, pit: { id: your_pit_id, keep_alive: 1m }, sort: [ { timestamp: asc }, { _id: asc } ], search_after: [1625097600000, 6Yd5eHQ] }优点提供数据一致性视图不受索引更新影响结合 Search After 的优势实现高效深度分页适合数据可能发生变更的场景缺点需要 ES 7.10 版本支持PIT 会占用额外内存实现相对复杂需要管理 PIT 的生命周期4. 性能对比分析性能对比表格分页方案性能表现内存占用实时性数据一致性适用场景传统分页(from/size)深度分页时性能差低高高浅分页(前几页)Scroll全量数据遍历高效高低(快照)高(快照)全量数据导出、批量处理Search After深度分页性能稳定低高低(数据变更影响)实时数据深度分页PIT深度分页性能稳定中(额外PIT开销)中(一致性视图)高(基于快照)数据变更场景的深度分页分页方案选择流程图浅分页深度分页是否是否开始分页查询分页深度如何使用传统from/size分页是否需要全量导出使用Scroll方案数据是否频繁变更使用PIT方案使用Search After方案5. 最小示例与注意事项Search After 最小示例from elasticsearch import Elasticsearch es Elasticsearch() # 第一次查询 response es.search( indexyour_index, body{ query: {match_all: {}}, size: 10, sort: [ {timestamp: asc}, {_id: asc} ] } ) # 获取下一页 last_sort_values response[hits][hits][-1][sort] response es.search( indexyour_index, body{ query: {match_all: {}}, size: 10, sort: [ {timestamp: asc}, {_id: asc} ], search_after: last_sort_values } )注意事项Search After 注意事项必须包含唯一排序字段避免重复数据如果排序数据发生变化需要重新开始分页适合顺序浏览但不适合随机跳转页面的场景Scroll 注意事项及时关闭不再使用的游标避免资源泄露不适合实时数据查询场景大数据量导出时建议分批处理并定期记录进度PIT 注意事项适当设置 keep_alive避免过早过期或占用过多资源完成分页后及时关闭 PIT在 ES 7.10 版本中使用确保集群支持通用注意事项根据实际场景选择最适合的分页方案考虑数据量和更新频率对性能的影响对于关键业务进行充分的性能测试监控查询性能及时发现潜在问题