ElasticSearch从入门到精通(持续更新....)—深度分页from-size|scroll|search_after

这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战

from+size

我们知道ElasticSearch分页的时候如果用from+size的话,from + size 默认不能超过1万条数据。在深度分页的情况下,这种使用方式效率是非常低的,比如 from = 5000, size=10, es 需要在各个分片上匹配排序并得到5000*10条有效数据,然后在结果集中取最后10条, es默认是10000条数据,可以通过设置max_result_window 值来改变最大数据量。

GET book_will/_search
{
    "from": 0,
    "size": 200
    "query": { "match_all": {}},
    "sort" : ["_doc"], 
    "size":  1000
}
复制代码

scroll

scroll 查询 可以用来对 Elasticsearch 有效地执行大批量的文档查询,而又不用付出深度分页那种代价。游标查询允许我们 先做查询初始化,然后再批量地拉取结果。 这有点儿像传统数据库中的 cursor

原理上是对某次查询生成一个游标 scroll_id , 后续的查询只需要根据这个游标去取数据,直到结果集中返回的 hits 字段为空,就表示遍历结束。scroll_id 的生成可以理解为建立了一个临时的历史快照,在此之后的增删改查等操作不会影响到这个快照的结果。scroll方式官方的建议并不是用于实时的请求,因为每一个 scroll_id 不仅会占用大量的资源(特别是排序的请求),而且是生成的历史快照,对于数据的变更不会反映到快照上。这种方式往往用于非实时处理大量数据的情况,比如要进行数据迁移或者索引变更之类的。

GET book_will/_search?scroll=1m 
{
    "query": { "match_all": {}},
    "sort" : ["_doc"], 
    "size":  1000
}
复制代码

tips:

scroll=1m 保持游标查询窗口一分钟。

"sort" : ["_doc"] 关键字 _doc 是最有效的排序顺序。

这个查询的返回结果包括一个字段 _scroll_id, 它是一个base64编码的长字符串 。

5002.png

现在我们能传递字段 _scroll_id 到 _search/scroll 查询接口获取下一批结果:

GET /_search/scroll
{
    "scroll": "1m", 
    "scroll_id" : "cXVlcnlUaGVuRmV0Y2g7NTsxMDk5NDpkUmpiR2FjOFNhNnlCM1ZDMWpWYnRROzEwOTk1OmRSamJHYWM4U2E2eUIzVkMxalZidFE7MTA5OTM6ZFJqYkdhYzhTYTZ5QjNWQzFqVmJ0UTsxMTE5MDpBVUtwN2lxc1FLZV8yRGVjWlI2QUVBOzEwOTk2OmRSamJHYWM4U2E2eUIzVkMxalZidFE7MDs="
}
复制代码

注意再次设置游标查询过期时间为一分钟。

这个游标查询返回的下一批结果。 尽管我们指定字段 size 的值为1000,我们有可能取到超过这个值数量的文档。 当查询的时候, 字段 size 作用于单个分片,所以每个批次实际返回的文档数量最大为 size * number_of_primary_shards 。

search_after

在第一次查询时,记录上一次查询的位置,在接下来的查询中获取到上次查询的位置,接着查询;第二次查询在第一次查询时的语句基础上添加search_after,并指明从哪个数据后开始读取。将search_after指定的值作为查询条件(类似游标),指定从整个有序数据哪个位置继续查询。

GET book_will/book/_search
{
    "size": 10,
    "query": {
        "match" : {
            "title" : "elasticsearch"
        }
    },
    "search_after": [1463538857, "tweet#654323"],
    "sort": [
        {"es_timestamp": "asc"},
        {"_uid": "desc"}
    ]
}
复制代码

from+ size分页、scroll滚动搜索、search_after 假分页比较

1.from + size分页性能低;优点是灵活性好,实现简单;缺点是存在深分页问题;适用于数据量比较小,能容忍深度分页存在的场景

2.scroll滚动搜索性能中等;优点解决了深度分页问题;缺点是无法反应数据的实时性(快照版本),需要维护一个 scroll_id,成本高;适用于需要查询海量结果集场景

3.search_after 假分页性能高;优点性能最好,不存在深度分页问题,能够反映数据的实时变更;缺点是实现复杂,需要有一个全局唯一的字段,连续分页的时每一次查询都需要上次查询的结果;适用于需海量数据的分页的场景

深度分页.png

注意:

使用完记得清除scroll: DELETE /_search/scroll/_all

//及时清除es快照,释放资源
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
clearScrollRequest.addScrollId(scrollId);
this.esSafeRestClient.clearScroll(clearScrollRequest,RequestOptions.DEFAULT);
复制代码

猜你喜欢

转载自juejin.im/post/7035994333132095501