elasticsearch 的滚动(scroll)

作者: 朱小虎XiaohuZhu | 来源:发表于2015-10-30 18:45 被阅读19052次

    Neil Zhu,简书ID Not_GOD,University AI 创始人 & Chief Scientist,致力于推进世界人工智能化进程。制定并实施 UAI 中长期增长战略和目标,带领团队快速成长为人工智能领域最专业的力量。
    作为行业领导者,他和UAI一起在2014年创建了TASA(中国最早的人工智能社团), DL Center(深度学习知识中心全球价值网络),AI growth(行业智库培训)等,为中国的人工智能人才建设输送了大量的血液和养分。此外,他还参与或者举办过各类国际性的人工智能峰会和活动,产生了巨大的影响力,书写了60万字的人工智能精品技术内容,生产翻译了全球第一本深度学习入门书《神经网络与深度学习》,生产的内容被大量的专业垂直公众号和媒体转载与连载。曾经受邀为国内顶尖大学制定人工智能学习规划和教授人工智能前沿课程,均受学生和老师好评。

    Scroll


    search 请求返回一个单一的结果“页”,而 scroll API 可以被用来检索大量的结果(甚至所有的结果),就像在传统数据库中使用的游标 cursor。

    滚动并不是为了实时的用户响应,而是为了处理大量的数据,例如,为了使用不同的配置来重新索引一个 index 到另一个 index 中去。

    client 支持:Perl 和 Python

    注意:从 scroll 请求返回的结果反映了 search 发生时刻的索引状态,就像一个快照。后续的对文档的改动(索引、更新或者删除)都只会影响后面的搜索请求。

    为了使用 scroll,初始搜索请求应该在查询中指定 scroll 参数,这可以告诉 Elasticsearch 需要保持搜索的上下文环境多久(参考Keeping the search context alive),如 ?scroll=1m

    curl -XGET 'localhost:9200/twitter/tweet/_search?scroll=1m' -d '
    {
        "query": {
            "match" : {
                "title" : "elasticsearch"
            }
        }
    }
    '
    

    使用上面的请求返回的结果中包含一个 scroll_id,这个 ID 可以被传递给 scroll API 来检索下一个批次的结果。

    curl -XGET  'localhost:9200/_search/scroll'  -d'
    {
        "scroll" : "1m", 
        "scroll_id" : "c2Nhbjs2OzM0NDg1ODpzRlBLc0FXNlNyNm5JWUc1" 
    }
    '
    
    • GET 或者 POST 可以使用
    • URL不应该包含 index 或者 type 名字——这些都指定在了原始的 search 请求中。
    • scroll 参数告诉 Elasticsearch 保持搜索的上下文等待另一个 1m
    • scroll_id 参数

    每次对 scroll API 的调用返回了结果的下一个批次知道没有更多的结果返回,也就是直到 hits 数组空了。

    为了向前兼容,scroll_idscroll 可以放在查询字符串中传递。scroll_id 则可以在请求体中传递。

    curl -XGET 'localhost:9200/_search/scroll?scroll=1m' -d 'c2Nhbjs2OzM0NDg1ODpzRlBLc0FXNlNyNm5JWUc1'
    

    注意:初始搜索请求和每个后续滚动请求返回一个新的 _scroll_id——只有最近的 _scroll_id 才能被使用。

    如果请求指定了聚合(aggregation),仅仅初始搜索响应才会包含聚合结果。

    使用 scroll-scan 的高效滚动

    使用 from and size 的深度分页,比如说 ?size=10&from=10000 是非常低效的,因为 100,000 排序的结果必须从每个分片上取出并重新排序最后返回 10 条。这个过程需要对每个请求页重复。

    scroll API 保持了哪些结果已经返回的记录,所以能更加高效地返回排序的结果。但是,按照默认设定排序结果仍然需要代价。

    一般来说,你仅仅想要找到结果,不关心顺序。你可以通过组合 scrollscan 来关闭任何打分或者排序,以最高效的方式返回结果。你需要做的就是将 search_type=scan 加入到查询的字符串中:

    curl -XGET 'localhost:9200/twitter/tweet/_search?scroll=1m&search_type=scan' -d '
    {
       "query": {
           "match" : {
               "title" : "elasticsearch"
           }
       }
    }
    '
    
    • 设置 search_typescan 可以关闭打分,让滚动更加高效。

    扫描式的滚动请求和标准的滚动请求有四处不同:

    • 不算分,关闭排序。结果会按照在索引中出现的顺序返回。
    • 不支持聚合
    • 初始 search 请求的响应不会在 hits 数组中包含任何结果。第一批结果就会按照第一个 scroll 请求返回。
    • 参数 size 控制了每个分片上而非每个请求的结果数目,所以 size10 的情况下,如果命中了 5 个分片,那么每个 scroll 请求最多会返回 50 个结果。

    如果你想支持打分,即使不进行排序,将 track_scores 设置为 true

    保持搜索上下文存活

    参数 scroll (传递给 search 请求还有每个 scroll 请求)告诉 Elasticsearch 应该需要保持搜索上下文多久。这个值(比如说 1m,详情请见the section called “Time units)并不需要长到可以处理所有的数据——仅仅需要足够长来处理前一批次的结果。每个 scroll 请求(包含 scroll 参数)设置了一个新的失效时间。

    一般来说,背后的合并过程通过合并更小的分段创建更大的分段来优化索引,同时会删除更小的分段。这个过程在滚动时进行,但是一个打开状态的搜索上下文阻止了旧分段在使用的时候不会被删除。这就是 Elasticsearch 能够不管后续的文档的变化,返回初始搜索请求的结果的原因。

    保持旧的分段存活意味着会产生更多的文件句柄。确保你配置了节点有空闲的文件句柄。参考File Descriptors

    你可以检查有多少搜索上下文开启了,

    curl -XGET localhost:9200/_nodes/stats/indices/search?pretty
    

    清除 scroll API

    搜索上下文当 scroll 超时就会自动移除。但是保持 scroll 存活需要代价,如在前一节讲的那样,所以 scrolls 当scroll不再被使用的时候需要被用 clear-scroll 显式地清除:

    curl -XDELETE localhost:9200/_search/scroll -d '
    { 
      "scroll_id" : ["c2Nhbjs2OzM0NDg1ODpzRlBLc0FXNlNyNm5JWUc1"]
    }'
    

    2.0.0-beta1 中加入。基于请求体的参数在 2.0.0 中加入。

    多个 scroll ID 可按照数据传入:

    curl -XDELETE localhost:9200/_search/scroll -d '
    { 
      "scroll_id" : ["c2Nhbjs2OzM0NDg1ODpzRlBLc0FXNlNyNm5JWUc1", "aGVuRmV0Y2g7NTsxOnkxaDZ"]
    }'
    

    2.0.0 中加入。

    所有搜索上下文可以通过 _all 参数而清除:

    curl -XDELETE localhost:9200/_search/scroll/_all
    

    scroll_id 也可以使用一个查询字符串的参数或者在请求的body中传递。多个scroll ID 可以使用逗号分隔传入:

    curl -XDELETE localhost:9200/_search/scroll \ -d 'c2Nhbjs2OzM0NDg1ODpzRlBLc0FXNlNyNm5JWUc1,aGVuRmV0Y2g7NTsxOnkxaDZ'
    

    相关文章

      网友评论

      • 269c74ec105c:《elasticsearch 的滚动(scroll) - 简书》写的不错不错,收藏了。

        推荐下,分布式作业中间件 Elastic-Job 源码解析 16 篇:http://yunai.coding.me/categories/Elastic-Job-Lite/?jianshu&404


        8afe04d66ee7:写的蛮用心的,希望多多坚持那
      • 水欣:为了使用 scroll,初始搜索请求应该在查询中指定 scroll 参数,这可以告诉 Elasticsearch 需要保持搜索的上下文环境多久(参考Keeping the search context alive),如 ?scroll=1m。这句话还是不太懂,可不可以再解释一下
      • 火星杰克_MJ:不知道你还能不能看到
      • 赵苏苏_5d86:那如果我要直接看第1000页,scroll怎么操作,怎么调用scroll_id
        zhaohz:@曹飞_00f1 这样的话还玩个妹啊
        曹飞_00f1:猜测是要自己调用1000次....把前面的数据给丢了才行
      • 小七奇奇:看了几篇也没明白这个scroll是怎么滚动的,既然我都用scan了,得到的结果只是统计文档的数量了,如何分页呢,然后这个scaoll还可以继续使用查询语句吗
      • 2ba349d33088:这是用机器翻译的么?
        朱小虎XiaohuZhu:@mark1608 不是
      • 5bf2de4c39c4:😄👌😄

      本文标题:elasticsearch 的滚动(scroll)

      本文链接:https://www.haomeiwen.com/subject/pmvfhttx.html