--- title: "滚动搜索" date: 2026-02-07 lastmod: 2026-02-07 description: "使用滚动上下文检索大量搜索结果" tags: ["搜索", "滚动", "大量数据"] summary: "使用滚动上下文从单个搜索请求中检索大量结果,保持搜索一致性视图。 API # 获取滚动结果 # GET /_search/scroll POST /_search/scroll GET /_search/scroll/{scroll_id} POST /_search/scroll/{scroll_id} 清除滚动上下文 # DELETE /_search/scroll DELETE /_search/scroll/{scroll_id} DELETE /_search/scroll/_all API 的作用 # 滚动搜索允许从单个搜索请求中检索大量结果(如 10,000+ 条)。 滚动搜索的特点 # 特点 描述 快照视图:保持搜索时的一致性视图 长时间保持:可设置保持时间(如 1 分钟) 内存消耗:每个滚动上下文占用内存 适用场景:数据导出、批处理、数据迁移 滚动 vs search_after # 方式 优点 缺点 Scroll 搜索一致性视图 占用内存 search_after 不占用内存,支持实时数据 需要排序字段 API 的参数 # GET/POST /_search/scroll # Query String 参数 # 参数 类型 是否必填 默认值 描述 scroll 时间值 否 初始搜索的时间 滚动上下文保持时间 scroll_id 字符串 否* - 滚动 ID(推荐在请求体中传递) rest_total_hits_as_int 布尔值 否 false hits." --- 使用滚动上下文从单个搜索请求中检索大量结果,保持搜索一致性视图。 ## API ### 获取滚动结果 ``` GET /_search/scroll POST /_search/scroll GET /_search/scroll/{scroll_id} POST /_search/scroll/{scroll_id} ``` ### 清除滚动上下文 ``` DELETE /_search/scroll DELETE /_search/scroll/{scroll_id} DELETE /_search/scroll/_all ``` ## API 的作用 滚动搜索允许从单个搜索请求中检索大量结果(如 10,000+ 条)。 ### 滚动搜索的特点 | 特点 | 描述 | |------|------| | **快照视图**:保持搜索时的一致性视图 | | **长时间保持**:可设置保持时间(如 1 分钟) | | **内存消耗**:每个滚动上下文占用内存 | | **适用场景**:数据导出、批处理、数据迁移 | ### 滚动 vs search_after | 方式 | 优点 | 缺点 | |------|------|------| | **Scroll** | 搜索一致性视图 | 占用内存 | | **search_after** | 不占用内存,支持实时数据 | 需要排序字段 | ## API 的参数 ### GET/POST /_search/scroll #### Query String 参数 | 参数 | 类型 | 是否必填 | 默认值 | 描述 | |------|------|----------|--------|------| | `scroll` | 时间值 | 否 | 初始搜索的时间 | 滚动上下文保持时间 | | `scroll_id` | 字符串 | 否* | - | 滚动 ID(推荐在请求体中传递) | | `rest_total_hits_as_int` | 布尔值 | 否 | false | hits.total 是否呈现为整数 | #### 请求体参数 ```json { "scroll": "1m", "scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAA..." } ``` 或数组格式: ```json { "scroll": "1m", "scroll_id": ["id1", "id2", "id3"] } ``` ### DELETE /_search/scroll #### Query String 参数 | 参数 | 类型 | 是否必填 | 描述 | |------|------|----------|------| | `{scroll_id}` | 字符串 | 否* | 要清除的滚动 ID | #### 请求体参数 ```json { "scroll_id": ["id1", "id2", "id3"] } ``` ## 示例 ### 初始滚动搜索 ```bash GET /my_index/_search?scroll=1m { "size": 100, "query": { "match_all": {} } } ``` **响应示例:** ```json { "_scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAA...", "took": 10, "timed_out": false, "_shards": { ... }, "hits": { "total": { "value": 1000, "relation": "eq" }, "hits": [ ... ] } } ``` ### 获取下一批结果 ```bash POST /_search/scroll { "scroll": "1m", "scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAA..." } ``` ### 获取多批结果 ```bash # 第一批 GET /my_index/_search?scroll=1m { "size": 100, "query": { "match_all": {} } } # 第二批 POST /_search/scroll { "scroll": "1m", "scroll_id": "从第一批响应中获取的 _scroll_id" } # 第三批 POST /_search/scroll { "scroll": "1m", "scroll_id": "从第二批响应中获取的 _scroll_id" } ``` ### 清除单个滚动上下文 ```bash DELETE /_search/scroll/DXF1ZXJ5QW5kRmV0Y2gBAAAA... ``` ### 清除所有滚动上下文 ```bash DELETE /_search/scroll/_all ``` ### 清除多个滚动上下文 ```bash DELETE /_search/scroll { "scroll_id": ["id1", "id2", "id3"] } ``` ### 处理空结果 当没有更多结果时: ```json { "_scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAA...", "took": 5, "timed_out": false, "_shards": { ... }, "hits": { "total": { "value": 1000, "relation": "eq" }, "hits": [] } } ``` ## 滚动参数说明 | 参数 | 格式示例 | 描述 | |------|----------|------| | `scroll` | `1m`、`10m`、`1h` | 滚动上下文保持时间 | | `scroll_id` | 64 字符编码字符串 | 滚动上下文的唯一标识符 | ## 滚动时间设置 | 时间 | 适用场景 | |------|----------| | `1m` | 默认推荐,适合大多数场景 | | `5m` | 较大的数据导出 | | `10m` | 大数据量处理 | | `1h` | 非常大的数据集(不推荐) | ## 使用场景 ### 场景 1:数据导出 ```bash # 初始搜索 GET /logs/_search?scroll=2m { "size": 1000, "query": { "range": { "@timestamp": { "gte": "2026-01-01", "lt": "2026-02-01" } } } } # 持续获取下一批 POST /_search/scroll { "scroll": "2m", "scroll_id": "..." } # 完成后清除 DELETE /_search/scroll/... ``` ### 场景 2:数据重新索引 ```bash GET /source_index/_search?scroll=5m { "size": 500, "_source": ["field1", "field2", "field3"] } ``` ### 场景 3:机器学习批处理 ```bash GET /training_data/_search?scroll=10m { "size": 1000, "query": { "match": { "category": "training" } } } ``` ## 响应字段说明 ### 滚动结果响应 | 字段 | 描述 | |------|------| | `_scroll_id` | 下一次滚动使用的 ID | | `took` | 执行时间(毫秒) | | `timed_out` | 是否超时 | | `_shards` | 分片信息 | | `hits.total` | 总命中数 | | `hits.hits` | 文档数组 | ### 滚动完成指示 当 `hits.hits` 为空数组时,表示已获取所有结果。 ## 最佳实践 ### 1. 及时清除上下文 ```bash # 完成后立即清除 DELETE /_search/scroll/scroll_id ``` ### 2. 使用合理的滚动时间 ```bash # 根据数据量设置 小数据集: scroll=1m 大数据集: scroll=5m ``` ### 3. 批量大小 ```bash { "size": 1000 # 推荐 500-1000 } ``` ### 4. 错误处理 当滚动上下文过期时: ```json { "error": { "type": "search_context_missing_exception", "reason": "No search context found for id [...]" } } ``` 需要重新执行初始搜索。 ## 注意事项 1. **内存消耗**:每个滚动上下文占用服务器内存 2. **实时性**:滚动期间的数据变化不会反映到结果中 3. **过期时间**:超过 scroll 时间未使用会自动清除 4. **URL 参数**:7.x 版本后不推荐通过 URL 传递 scroll_id 5. **清除**:完成后务必清除滚动上下文 ## 性能考虑 | 操作 | 性能影响 | |------|----------| | 长时间滚动 | 持续占用内存 | | 大批量大小 | 单次请求时间增加 | | 多并发滚动 | 内存消耗大 | | 超时时间 | 内存释放延迟 |