如何解决 ES elasticsearch 深度分页查询的问题?

2 个回答

  • 格列柯南
    杯中之物从来不能消愁补过
    ### 解决 Elasticsearch 深度分页查询的问题 在 Elasticsearch 中,深度分页查询可能导致性能问题。以下是两种常用的解决方案:Scroll 和 search_after。 ### Scroll 遍历查询 #### 定义与实战案例 Scroll API 可用于从单个搜索请求中检索大量结果,其方式与传统数据库中的游标(cursor)类似。相比于 `From + size` 和 `search_after` 返回一页数据,Scroll 更适用于全量遍历数据。Scroll 核心执行步骤如下: ##### 步骤 1:指定检索语句同时设置 Scroll 上下文保留时间 Scroll 默认包含了 search_after 的 PIT(Point In Time)视图或快照功能。从 Scroll 请求返回的结果反映了发出初始搜索请求时索引的状态,类似在那一个时刻做了快照。 ```sql # 这边会返回 scroll id GET /content/_search?scroll=5m { "query": { "match_all": {}}, "sort" : ["_doc"], "size": 1 } # 拿着 scroll_id 就可以一直向下查了 GET /_search/scroll { "scroll": "1m", "scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFDNpWTZmWDhCWTdPTTJkS2hJZFlqAAAAAACuVJ8WRWM2Z3VZcHVRV2EyUS1fTENMMl9Idw==" } ``` #### 优缺点及适用场景 ##### 优点 - 支持全量遍历。 ##### 缺点 - 响应时间非实时。 - 保留上下文需要足够的堆内存空间。 ##### 适用场景 - 全量或数据量很大时遍历结果数据,而非分页查询。 官方建议:不再建议使用 Scroll API 进行深度分页。如果要分页检索超过 Top 10,000+ 结果时,推荐使用:PIT + search_after。 ### search_after 查询 #### 定义与实战案例 search_after 查询本质:使用前一页中的一组排序值来检索匹配的下一页。 ##### 前置条件 - 使用 search_after 要求后续的多个请求返回与第一次查询相同的排序结果序列。 ##### 实现 可以创建一个时间点 Point In Time(PIT)保障搜索过程中保留特定事件点的索引状态。PIT 是 Elasticsearch 7.10 版本之后的新特性。 ##### 注意事项 - sort 是一个组合键,要确保唯一。第一次查询带出来,下一次查询时带上每次都要换。 ```sql POST content/_search { "size": 1, "query": { "match_all": {} }, "sort": [ {"createTime": "desc"} , {"_id": "asc"} ] } POST content/_search { "size": 1, "query": { "match_all": {} }, "search_after": [ 1646956800000, "427:3" ], "sort": [ {"createTime": "desc"} , {"_id": "asc"} ] } ``` 通过以上两种方式,可以有效解决 Elasticsearch 的深度分页问题,根据具体需求选择合适的方法。
    编辑于 2023-10-28 11:38 •IP属地 福建
    举报
    评论
    收藏

  • 周维清
    能治愈生活的良方,是保持对生活的热爱。
    在 Elasticsearch 中,**深度分页**问题是指在对大量数据进行分页查询时,使用传统的 `from` 和 `size` 参数分页会导致性能问题。随着 `from` 值的增大,查询所需的资源和处理时间会急剧增加,可能会导致查询超时或系统负载过高。这是因为 Elasticsearch 必须跳过前面所有页的数据才能返回目标页的数据。 ### 1. 深度分页问题的成因 当我们进行分页查询时,例如请求第 1000 页,每页 10 条记录,Elasticsearch 需要先扫描前 9990 条记录,然后再返回所需的 10 条记录。这个过程会占用大量的 CPU 和内存资源,特别是在数据量较大的情况下,性能问题尤为明显。因此,Elasticsearch 限制了 `from + size` 的最大值,默认最大为 10000,超过该值将导致查询失败。 ### 2. 解决深度分页问题的方案 #### 方案 1:使用 Scroll API `Scroll API` 专为大数据集的遍历设计,适合于需要导出或批量处理大量数据的场景。 - **原理**:Scroll 创建一个数据快照,以固定视图返回数据,即使数据在查询期间发生变化,Scroll 也能确保返回的结果是一致的。 - **使用方法**: 1. 初始化一个带 `scroll` 参数的查询,返回第一批数据和一个 `scroll_id`。 2. 使用返回的 `scroll_id` 获取下一批数据。 3. 重复该过程,直到获取完所有结果。 - **优缺点**: - **优点**:避免了重复排序,提供了数据的一致快照,减少了资源消耗。 - **缺点**:Scroll 在维护游标时会占用较多资源,不适合实时响应的查询场景。 #### 方案 2:使用 search_after `search_after` 是另一种用于深度分页的方法,它适合于需要深度分页且保证数据顺序访问的情况。 - **原理**:基于上一次查询的结果,`search_after` 使用最后一条记录的排序值来获取下一批数据。 - **使用方法**: 1. 第一次查询时定义一个排序规则,例如按时间戳和 `_id` 排序。 2. 在后续查询中,使用上次查询结果的最后一条记录的排序值作为 `search_after` 参数。 3. 迭代查询下一批数据。 - **优缺点**: - **优点**:避免了跳过大量数据的操作,适合深度分页;不需要重复扫描。 - **缺点**:不支持随机页访问,且需要数据有唯一排序字段。 #### 方案 3:使用深度分页限制结合业务方案优化 - **分段查询**:对于极大数据量,可以考虑结合业务需求,将查询结果分段返回,或在客户端实现类似“加载更多”的效果,减少单次查询的数据量。 - **分片索引**:将数据按日期、类型等划分到不同的索引中,减小单次查询的数据量,从而提高查询性能。 ### 3. 方案选择 | 方案 | 使用场景 | 优点 | 缺点 | |-----------------|--------------------------------|------------------------------|--------------------------------| | 传统分页 | 小数据集、用户界面分页 | 简单直接、实现方便 | 性能较差,不适合深度分页 | | Scroll API | 数据导出、备份、批量数据处理 | 支持一致性视图、减少排序 | 不适合实时请求,高资源消耗 | | search_after | 深度分页、顺序遍历 | 高性能、避免跳过大量数据 | 不支持随机页,需维护排序字段 | | 分段查询/分片索引 | 极大数据量且需优化查询性能 | 灵活性高 | 需结合业务逻辑 | ### 4. 总结 - **Scroll API**:适合于大数据导出或数据分析场景,保证一致性但资源消耗较高。 - **search_after**:适合深度分页并提供高效查询,不适合随机访问。 - **业务分段查询**:适合极大数据量、需分页但不要求实时响应的场景。 选择适当的分页方式可以有效提升 Elasticsearch 在深度分页场景下的性能。
    发布于 2023-06-28 23:03 •IP属地 云南
    举报
    评论
    收藏