• -------------------------------------------------------------
  • ====================================

正确遍历ElasticSearch索引

elasticsearch dewbay 6年前 (2019-04-12) 2669次浏览 已收录 0个评论 扫描二维码

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。


露水湾 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:正确遍历ElasticSearch索引
喜欢 (0)
[]
分享 (0)
关于作者:
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址