前言
在分布式系统中深度分页
理解为什么深度分页是有问题的,我们可以假设在一个有 5 个主分片的索引中搜索。 当我们请求结果的第一页(结果从 1 到 10 ),每一个分片产生前 10 的结果,并且返回给协调节点,协调节点对 50 个结果排序得到全部结果的前 10 个。
现在假设我们请求第 1000 页--结果从 10001 到 10010 。所有都以相同的方式工作除了每个分片不得不产生前10010个结果以外。 然后协调节点对全部 50050 个结果排序最后丢弃掉这些结果中的 50040 个结果。
可以看到,在分布式系统中,对结果排序的成本随分页的深度成指数上升。这就是 web 搜索引擎对任何查询都不要返回超过 1000 个结果的原因。
分页方式
- from+size
常见深度分页方式。from表示从第几行开始,size表示查询多少条文档。from默认为0,size默认为10, size的大小不能超过index.max_result_window这个参数的设置,默认为10,000。 - scroll
对某次查询生成一个游标 scroll_id , 后续的查询只需要根据这个游标去取数据,直到结果集中返回的 hits 字段为空,就表示遍历结束。scroll_id 的生成可以理解为建立了一个临时的历史快照,在此之后的增删改查等操作不会影响到这个快照的结果。 - search_after
提供一个live cursor来规避消耗存储和时间的性能问题,将上一页查询的最后一条数据作为下一条数据的搜索条件,必须有全局唯一字段来排序,如业务唯一标识字段或elasticsearch自带的_id字段。
适用于深度分页+ 排序,因为每一页的数据依赖于上一页最后一条数据,所以无法跳页请求。且返回的始终是最新的数据,在分页过程中数据的位置可能会有变更。
优劣分析
分页方式 | 是否有页数限制 | 是否可以跳页 | 性能 | 耗费资源 | 实时性 | 常用场景 |
---|---|---|---|---|---|---|
from+size | 有,受参数限制,可调整 | 是 | 分页越深,性能指数倍下降 | 分页越深,耗费资源指数倍增长 | 实时 | 常见的搜索场景都可以满足,需限制页数 |
scroll | 无 | 否 | 高 | 第一次查询时缓存查询结果耗费资源较多,后续基本无耗费 | 非实时 | 后台批量导出任务、数据迁移任务 |
search_after | 无 | 否 | 中 | 第一次查询时缓存查询结果耗费资源较多,后续按上次查询结果取数据 | 实时 | 有实时性要求的批量任务 |
最终方案
思考:业务方哪种需求需要用elasticsearch搜索查看超过10000条的数据?考虑尽可能多的条件过滤出真实需要的数据
- 业务自主查询限制页数。采用尽可能多的查询条件,限制查询结果在10000条以内,使用from+size灵活查询
- 性能与业务择中,业务侧限制分页方式。只能查询下一页,无法跳页,此方式可使用search_after查询