Elasticsearch 滚动(Scroll)用法、使用场景及与扫描(Scan)的区别

发布于:2025-07-12 ⋅ 阅读:(15) ⋅ 点赞:(0)

在 Elasticsearch 7.x 版本的大规模数据检索场景中,传统分页方式的局限性愈发明显。扫描(Scan)和滚动(Scroll)机制作为高效处理全量数据的核心方案,在该版本中有着明确的特性定位和使用规范。本文将基于 Elasticsearch 7.x 版本,详细解析两者的作用、使用场景、具体用法及核心区别。

一、ES滚动(Scroll)作用和意义

Elasticsearch 7.x 中,传统的 from + size 分页方式依然受限于 index.max_result_window 参数(默认值 10000),当需要获取超过该限制的数据或进行全量遍历的时,性能会急剧下降。而扫描和滚动机制正是为解决这一问题而生。

滚动(Scroll) 的作用是通过创建搜索结果的 “快照”,生成唯一的滚动 ID(Scroll ID),允许后续通过该 ID 分批获取全部结果。它保留搜索上下文,避免每次分页都重新执行搜索和排序操作,从而高效支持海量数据的全量遍历,且不受 max_result_window 限制。

扫描(Scan) 在 Elasticsearch 7.x 中已不再通过 search_type=scan 参数启用,而是作为滚动机制的一种特殊模式存在 —— 即禁用排序的滚动。其作用是在滚动的基础上进一步降低性能开销,通过跳过结果排序步骤,仅按文档在分片上的原生存储顺序返回数据,专注于纯全量数据提取场景。

二、ES滚动(Scroll)使用场景

在 Elasticsearch 7.x 中,扫描和滚动的特性决定了它们适用于不同的业务场景。

滚动(Scroll) 适用于需要有序结果的全量数据遍历场景。例如,在日志分析系统中,需要按时间戳降序导出最近一个月的错误日志,用于排查系统故障规律;在内容平台中,按文章发布时间排序导出热门文章数据,生成月度内容总结报表。这些场景下,结果的有序性是核心需求,滚动机制能在保证顺序的同时高效完成全量数据获取。

扫描(Scan,即禁用排序的滚动) 则适用于无需排序的全量数据处理场景。比如,在数据迁移过程中,将 Elasticsearch 中的历史数据全量导出至数据仓库;进行数据备份时,批量提取全量文档并存储至备份介质;在数据清洗前,获取原始数据进行字段完整性校验等。这类场景更关注数据提取的效率,对结果顺序无要求,扫描模式能以更低的性能开销完成任务。

三、具体用法

(一)滚动(Scroll)的用法

滚动操作在 7.x 版本中流程清晰,主要包括初始化滚动、批量获取结果和清理滚动上下文三个步骤。

1、初始化滚动搜索:

通过在请求 URL 中添加 scroll 参数指定搜索上下文的保留时间(如 scroll=10m 表示保留 10 分钟),在请求体中设置 size 定义每批返回的文档数量,并配置排序条件(若需要)。请求会返回第一批结果和 _scroll_id。

示例请求:

POST /my_index/_search?scroll=10m
{
    "size": 200, // 每批返回 200 条文档
    "query": {
        "range": {
            "create_time": {
                "gte": "2023-01-01",
                "lte": "2023-12-31"
                  }
                }
    },
    "sort": [{"create_time": "asc"}] // 按创建时间升序排序
}

返回结果中,_scroll_id 用于后续批量获取,hits 包含第一批符合条件的文档。

2、批量获取后续结果:

使用初始化返回的 _scroll_id 发送滚动请求,每次请求会返回下一批结果。需注意在请求中再次指定 scroll 参数,延长搜索上下文的保留时间。重复此步骤,直到 hits.hits 为空,即表示已获取全部结果。

示例请求:

POST /_search/scroll
{
    "scroll": "10m", // 延长上下文保留时间
    "scroll_id": "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFnV...==" // 上一步返回的            滚动 ID
}

3、清理滚动上下文:

滚动上下文会占用集群内存资源,完成数据获取后需主动清理。可通过指定 scroll_id 删除单个上下文,或删除所有未过期的滚动上下文。

示例请求(删除单个上下文):

DELETE /_search/scroll
{
    "scroll_id": "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFnV...=="
}

4、删除所有上下文:

DELETE /_search/scroll/_all

(二)扫描(Scan)的用法(7.x 版本实现方式)

在 Elasticsearch 7.x 中,search_type=scan 参数已被彻底移除,扫描模式通过 “禁用排序的滚动” 实现,用法与滚动类似,但需在请求中明确关闭排序。

  1. 初始化扫描模式(禁用排序的滚动):与滚动初始化步骤相同,需添加 scroll 参数和 size 参数,但在请求体中设置 sort: [] 或不指定任何排序条件,以禁用结果排序。

示例请求:

POST /my_index/_search?scroll=10m
{
    "size": 200,
    "query": {
            "match_all": {} // 匹配所有文档,可根据需求替换为具体查询条件
      },
       "sort": [] // 禁用排序,启用扫描模式
}

  1. 批量获取结果:与滚动机制完全一致,通过初始化返回的 scroll_id 分批获取数据,直到 hits.hits 为空。由于禁用了排序,返回的文档顺序仅由文档在分片上的存储顺序决定,不保证全局有序。

  2. 清理滚动上下文:与滚动操作相同,完成数据提取后需主动删除 scroll_id,释放集群资源。

四、区别(基于 Elasticsearch 7.x)

在 Elasticsearch 7.x 版本中,扫描(禁用排序的滚动)与滚动的区别主要体现在排序特性、性能开销、结果顺序和实现方式上:

对比维度

滚动(Scroll)

扫描(Scan,禁用排序的滚动)

排序配置

支持自定义排序(如按字段、评分排序),需在请求中指定 sort 条件

必须禁用排序,请求中需设置 sort: [] 或不配置排序

性能表现

因排序操作消耗计算资源,性能略低

无排序计算开销,性能优于滚动模式

结果顺序

基于排序条件实现全局有序

按文档在分片的原生顺序返回,全局无序

适用场景

需要有序结果的全量遍历(如按时间排序导出数据)

无需排序的全量数据提取(如数据迁移、备份)

实现方式

通过 scroll 参数启用,需配置排序条件

通过 scroll 参数 + 禁用排序实现,无独立参数

版本兼容性

完全支持,无废弃风险

替代 search_type=scan 的推荐实现方式

五、使用注意事项(基于 Elasticsearch 7.x)

  1. 滚动上下文有效期:scroll 参数指定的是每次请求后上下文的存活时间,需确保批量获取间隔不超过该时间,否则上下文失效需重新初始化。建议根据数据量和处理速度合理设置,避免过短导致频繁重新初始化,或过长浪费资源。

  2. 内存资源管理:滚动上下文会占用集群内存,尤其是在处理超大规模数据时,未及时清理的 scroll_id 可能导致内存泄露。建议使用完毕后立即执行删除操作,或通过监控工具跟踪未清理的滚动上下文。

  3. 数据实时性限制:滚动基于初始化时的结果快照,无法获取初始化后新增、修改或删除的文档。若需实时数据,需重新发起滚动请求。

  4. 分片与 size 参数:size 参数定义的是每个分片返回的文档数,实际每批结果数为 size × 分片数。需根据集群分片数量合理设置 size,避免单次返回数据量过大导致网络拥堵。


网站公告

今日签到

点亮在社区的每一天
去签到