使用 ES 做搜索引擎拉取数据的时候, 如果数据量太大, 通过传统的 from + size 的方式并不能获取所有的数据 (默认最大记录数 10000), 因为随着页数的增加, 会消耗大量的内存, 导致 ES 集群不稳定.
ES 提供了 3 中解决深度翻页的操作, 分别是 scroll,sliced scroll 和 search after.
scroll
scroll API 提供了一个全局深度翻页的操作, 首次请求会返回一个 scroll_id, 使用该 scroll_id 可以顺序获取下一批次的数据; scroll 请求不能用来做用户端的实时请求, 只能用来做线下大量数据的翻页处理, 例如数据的导出, 迁移和_reindex 操作, 还有同一个 scroll_id 无法并行处理数据, 所以处理完全部的数据执行时间会稍长一些.
例如我们使用 scroll 翻页获取包含 Elasticsearch 的 Twitter, 那么首次请求的语句如下:
- POST /Twitter/_search?scroll=1m
- {
- "size": 100,
- "query": {
- "match" : {
- "title" : "elasticsearch"
- }
- }
- }
其中 scroll=1m 是指 scroll_id 保留上下文的时间
首次请求会返回一个 scroll_id, 我们根据这个值去不断拉取下一页直至没有结果返回:
- POST /_search/scroll
- {
- "scroll" : "1m",
- "scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ=="
- }
针对 scroll API 下, 同一个 scroll_id 无法并行处理数据的问题, es 又推出了 sliced scroll, 与 scroll API 的区别是 sliced scroll 可以通过切片的方式指定多 scroll 并行处理.
sliced scroll
sliced scroll API 除指定上下文保留时间外, 还需要指定最大切片和当前切片, 最大切片数据一般和 shard 数一致或者小于 shard 数, 每个切片的 scroll 操作和 scroll API 的操作是一致的:
- GET /Twitter/_search?scroll=1m
- {
- "slice": {
- "id": 0,
- "max": 2
- },
- "query": {
- "match" : {
- "title" : "elasticsearch"
- }
- }
- }
- GET /Twitter/_search?scroll=1m
- {
- "slice": {
- "id": 1,
- "max": 2
- },
- "query": {
- "match" : {
- "title" : "elasticsearch"
- }
- }
- }
因为支持并行处理, 执行时间要比 scroll 快很多.
search after
上面两种翻页的方式都无法支撑用户在线高并发操作, search_after 提供了一种动态指针的方案, 即基于上一页排序值检索下一页实现动态分页:
首次查询
- GET Twitter/_search
- {
- "size": 10,
- "query": {
- "match" : {
- "title" : "elasticsearch"
- }
- },
- "sort": [
- {"date": "asc"},
- {"tie_breaker_id": "asc"}
- ]
- }
因为是动态指针, 所以不需要像 scroll API 那样指定上下文保留时间了.
通过上一页返回的 date + tie_breaker_id 最后一个值做为这一页的 search_after:
- GET Twitter/_search
- {
- "size": 10,
- "query": {
- "match" : {
- "title" : "elasticsearch"
- }
- },
- "search_after": [1463538857, "654323"],
- "sort": [
- {"_score": "desc"},
- {"tie_breaker_id": "asc"}
- ]
- }
说白了 search_after 并没有解决随机跳页查询的场景, 但是可以支撑多 query 并发请求; search_after 操作需要指定一个支持排序且值唯一的字段用来做下一页拉取的指针, 这种翻页方式也可以通过 bool 查询的 range filter 实现.
来源: http://www.tuicool.com/articles/qURfMnu