• 正确遍历ElasticSearch索引


    1:ElasticSearch的查询过程

    2:由ES查询模式引起的深度分页问题

    3:如何正确遍历索引中的数据


     

    ElasticSearch的查询过程

    es的数据查询分两步:

    第一步是的结果是获取满足查询条件的,分布于各个shard上的_doc_id及对应_score;

    第二步是根据第一步获取的所有的_doc_id,去各个shard上获取数据明细,合并返回客户端。

    在第一步的查询中,es执行了一个类似map-reduce的查询模式:在各个shard上执行同样的查询,获取同样大小的数据(from+size),然后将各个 shard查询结果的_doc_id,_score返回给接收查询请求的节点,最终进行一次汇总。注意这里传输数据的数量是from+size,而不仅仅是size大小。


    由ES查询模式引起的深度分页问题

    通过ES的查询过程我们已经可以看出问题,对大数据量的Index进行遍历操作,如果使用from size的方式,将存在极大的资源浪费(因为from过大),当然如果size过大则问题更为严重,服务器内存会被吃光。因此很多站点的查询,都不会允许查看过大的page,深度分页的问题在关系数据库中同样存在。


    如何正确遍历索引中的数据

    在ES中遍历索引的推荐方式是采用scroll操作,或者在不需要排序而仅仅需要遍历的情况下,可以采用scroll_scan进一步提升性能。

    详细可见:Scroll的官方说明

    简单描述一下Scroll的工作原理:

    1:对需要遍历(或获取某个满足条件的子集)的索引,规划一个合理的size作为分页大小;

    2:在POST的查询中,增加?scroll=1m(expire time)的query string;

    3:在该次查询中,返回结果中除了查询结果以外,还有一个scroll_id(很长),这个scroll_id可以看做是第一次查询时目标索引的快照的游标

    4:之后直接在GET请求中将scroll_id作为query string传递,或在POST请求中加入scroll_id即可获取下一批数据,直到没有数据为止,如此实现对所有目标数据的遍历。

    (注:在使用scroll遍历的过程中,不需要再指定各种查询条件比如索引名,size大小什么的,只需要指定scroll_id即可,还可以指定scroll:1m之类的过期时间,相同条件下有效期内的scroll操作,返回的scroll_id是不会变的,仅仅是scroll_id这个游标向前走,返回下一批数据而已)

    scroll_id可以被显式删除,如果你需要重置对查询目标的遍历过程的话。

    如果遍历过程不需要对数据进行排序,可以使用更为高效的scroll_scan方式进行,如下:

    POST ip:port/my_index/my_type/_search?search_type=scan&scroll=1m&size=50
    {
        "query": { "match_all": {}}
    }

    这里需要注意的是,search_type指定为scan,即无需排序,而size=50是指每个shard上的size是50,最终返回数据是shard*size。

    初次以外,scroll_scan与普通的scroll还有如下三点不同:

    1. Scroll-Scan 结果没有排序,按 index 顺序返回,没有排序,可以提高取数据性能。
    2. 初始化时只返回 _scroll_id,没有具体的 hits 结果
    3. size 控制的是每个分片的返回的数据量而不是整个请求返回的数据量

    关于scroll操作是否线程安全的问题,es的客户端(java&c#)均为线程安全,因此我认为通过客户端来进行的scroll请求也是线程安全的。如果有错误请指出。

    2016-09-14补充:

    利用scroll_id获取数据的同时,ES将返回当前查询的scroll_id,在其失效或被删除之前,这个scroll_id都不变,如果希望程序的可靠性更高,可以用每次返回的scroll_id更新查询POST所发送的scroll_id;同时,对通过scroll_id查询返回的结果集进行判空,以确定当前scroll_id是否已失效,从而需要重新获取scroll_id。

  • 相关阅读:
    Java LinkList遍历方式
    Java LinkedList的实现原理
    ArrayList 原理(2)
    ArrayList 原理(1)
    Java中HashMap的实现原理
    Java HashMap两种遍历方式
    【转】Unity3d:读取FBX中的动画
    C#与U3D中字符串尾0
    U3D中的又一个坑
    MaxScript 学习笔记【有转载】
  • 原文地址:https://www.cnblogs.com/you-you-111/p/5849945.html
Copyright © 2020-2023  润新知