elasticsearch深度分页问题

本文详细探讨了Elasticsearch中深度分页的三种方式:from + size由于效率低和最大限制10000导致的问题,scroll如何作为大数据集的解决方案,以及search_after如何在保持实时性的同时解决深度分页。通过对每种方法的解释和示例,展示了它们的适用场景和优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、深度分页方式 from + size

es 默认采用的分页方式是from+size的形式,在深度分页的情况下,这种使用方式效率是非常低的,比如我们执行如下查询

1 GET /student/student/_search
2 {
   
   
3   "query":{
   
   
4     "match_all": {
   
   }
5   },
6   "from":5000,
7   "size":10
8 }

意味着 es 需要在各个分片上匹配排序并得到5010条数据,协调节点拿到这些数据再进行排序等处理,然后结果集中取最后10条数据返回。
我们会发现这样的深度分页将会使得效率非常低,因为我只需要查询10条数据,而es则需要执行from+size条数据然后处理后返回。
其次:es为了性能,限制了我们分页的深度,es目前支持的最大的 max_result_window = 10000;也就是说我们不能分页到10000条数据以上。

例如:
在这里插入图片描述

from + size <= 10000所以这个分页深度依然能够执行。
在这里插入图片描述
继续看上图,当size + from > 10000;es查询失败,并且提示

Result window is too large, from + size must be less than or equal to: [10000] but was [10001]

接下来看还有一个很重要的提示

See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting

有关请求大数据集的更有效方法,请参阅滚动api。这个限制可以通过改变[索引]来设置。哦呵,原来es给我们提供了另外的一个API scroll。难道这个 scroll 能解决深度分页问题?

二、深度分页之scroll

在es中如果我们分页要请求大数据集或者一次请求要获取较大的数据集,scroll都是一个非常好的解决方案。

使用scroll滚动搜索,可以先搜索一批数据,然后下次再搜索一批数据,以此类推,直到搜索出全部的数据来scroll搜索会在第一次搜索的时候,保存一个当时的视图快照,之后只会基于该旧的视图快照提供数据搜索,如果这个期间数据变更,是不会让用户看到的。每次发送scroll请求,我们还需要指定一个scroll参数,指定一个时间窗口,每次搜索请求只要在这个时间窗口内能完成就可以了。

一个滚屏搜索允许我们做一个初始阶段搜索并且持续批量从Elasticsearch里拉取结果直到没有结果剩下。这有点像传统数据库里的cursors(游标)。

滚屏搜索会及时制作快照。这个快照不会包含任何在初始阶段搜索请求后对index做的修改。它通过将旧的数据文件保存在手边,所以可以保护index的样子看起来像搜索开始时的样子。这样将使得我们无法得到用户最近的更新行为。

scroll的使用很简单
执行如下curl,每次请求两条。可以定制 scroll = 5m意味着该窗口过期时间为5分钟。

1 GET /student/student/_search?scroll=5m
2 {
   
   
3   "query": {
   
   
4     "match_all": {
   
   }
5   },
6   "size": 2
7 }
 1 {
   
   
<think>嗯,用户想了解Elasticsearch深度分页查询Search_after,并且要求图文教程。首先,我得回忆一下Search_after的作用和适用场景。记得之前学的时候,Elasticsearch分页有from+size的方式,但深度分页时性能会下降,特别是数据量大的时候。Search_after应该是解决这个问题的。 那Search_after的原理是什么呢?应该是基于上一页的排序值来获取下一页的数据,避免深度翻页时的性能损耗。不过需要基于唯一的排序字段,比如时间戳或者_id,否则可能会有重复。要确保排序字段的值是唯一的,否则分页可能会出错。 接下来,用户可能需要具体的步骤和示例。应该分步骤讲解,先讲前置条件,比如索引创建和数据准备,然后讲如何第一次查询,获取search_after的值,再讲如何用这个值进行下一页的查询。同时要注意,使用Search_after时必须指定排序,而且排序字段要唯一,否则分页可能不准确。 可能还需要对比一下Search_after和Scroll API的区别,Scroll适合大量数据导出,而Search_after适合实时分页。另外,用户可能想知道Search_after的优缺点,比如不能跳页,只能逐页翻,但性能更好。 图文教程的话,可能需要插入一些示例代码和结果截图。虽然现在不能实际贴图,但可以用文字描述示例输出,比如第一次查询返回的数据和sort值,下一页查询使用search_after参数的情况。 还要注意用户可能遇到的常见问题,比如排序字段不唯一导致分页重复或遗漏,或者忘记添加排序条件。需要提醒用户确保排序字段的唯一性,比如使用_id作为第二排序字段。 最后,总结一下适用场景,比如移动端加载更多,或者需要深度分页但不需要跳页的情况。可能用户的实际应用场景是这样的,所以明确说明Search_after的适用性很重要。</think>Elasticsearch 深度分页查询 Search_after 图文教程(文字版) 一、为什么需要 Search_after? ![分页性能对比图] 传统分页(from+size)在深度分页时性能骤降,Search_after 通过游标机制实现高效深度分页,适合处理百万级数据的分页场景。 二、核心原理 1. 基于排序字段的值作为游标 2. 每次查询携带上一页最后一条的排序值 3. 避免全局排序,性能损耗稳定($O(1)$) 三、具体使用步骤 1. 前置条件:创建测试索引 ```json PUT /products { "mappings": { "properties": { "name": { "type": "text" }, "price": { "type": "double" }, "timestamp": { "type": "date" } } } } ``` 2. 首次查询(必须包含排序) ```json GET /products/_search { "size": 2, "sort": [ { "timestamp": "desc" }, { "_id": "asc" } // 确保排序唯一性 ] } ``` 响应示例: ```json { "hits": { "hits": [ { "_id": "1", "_source": { "name": "Phone", "price": 599.99 }, "sort": [1658800000000, "1"] }, { "_id": "2", "_source": { "name": "Laptop", "price": 1299.99 }, "sort": [1658700000000, "2"] } ] } } ``` 3. 后续查询使用 search_after ```json GET /products/_search { "size": 2, "sort": [ { "timestamp": "desc" }, { "_id": "asc" } ], "search_after": [1658700000000, "2"] // 使用上页最后记录的sort值 } ``` 四、注意事项(⚠️关键点) 1. 必须指定唯一性排序组合(推荐:业务字段 + _id) 2. 不能跳页查询,只能顺序翻页 3. 索引更新可能导致分页结果变化(实时性特征) 4. 需要客户端维护上下文状态 五、与 Scroll API 对比 | 特性 | Search_after | Scroll | |---------------------|------------------------|----------------------| | 实时性 | ✅ 实时 | ❌ 快照 | | 内存消耗 | 低 | 高 | | 适用场景 | 用户实时分页 | 大数据量导出 | | 最大返回 | 无限制 | 取决于设置 | 六、最佳实践 1. 组合排序字段示例: ```json "sort": [ { "create_time": "desc" }, { "score": "desc" }, { "_id": "asc" } ] ``` 2. 客户端实现逻辑: ``` 首次查询 → 保存sort值 → 下次请求携带search_after → 循环直到无结果 ``` 七、常见问题解决 1. 出现重复数据 → 检查排序字段唯一性 2. 分页中断 → 确保使用相同的排序条件 3. 性能下降 → 避免在text字段上排序 适用场景:移动端「加载更多」、日志分批处理、大数据量报表生成等需要深度分页但不需要跳页的场合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖天才小朱(怀玉)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值