怎么高雅的全量读取Elasticsearch索引里边的数据ITeye - 牛牛娱乐

怎么高雅的全量读取Elasticsearch索引里边的数据ITeye

2019-01-10 14:23:07 | 作者: 映秋 | 标签: 数据,读取,索引 | 浏览: 1288


### (一)scroll的介绍

有时分咱们或许想要读取整个es索引的数据或许其间的大部分数据,来重建索引或许加工数据,信任大多数人都会说这很简单啊直接用from+size就能搞定,但实际情况是from+size的分页办法不适合用于这种全量数据的抽取,越到后边这种办法的功能就越低,这也是es里边为什么约束了单次查询成果的数据不能超过1万条数据的原因。


es里边供给了scroll的办法来全量读取索引数据其与数据库里边的游标(cursor)的概念十分相似,运用scroll读取数据的时分,只需求发送一次查询恳求,然后es服务端会生成一个当时恳求索引的快照数据集,接着咱们每次经过scrollId来读取指定巨细的批次数据,直到把整个索引的数据读取结束。

这里边需求留意,当索引快照集生成的时分,其实在es内部保护了一个search context的上下文,这个上下文在指定的时刻距离内是只读的和不可变的,也便是只需它生成,那么后续你的增加,删去,更新操作的数据都不会被感知。


### (二)scroll的运用

下面看下怎么运用:


(1)要运用scroll办法来读取数据,需求两步操作,第一步先做一个search context的初始化操作,如下指令:
````
curl -XGET localhost:9200/twitter/tweet/_search?scroll=1m -d 
 "query": {
 "match" : {
 "title" : "elasticsearch"
````


留意上面url里边的scroll=1m代表,这个search context只保存一分钟的有效期。

(2)在第一步操作里边咱们能够获取一个scrollId,然后后边的每个读取都会得到一个scrollId,咱们在读取next批次的数据要把这个scrollId回传,如下:

````
curl -XGET localhost:9200/_search/scroll -d
 "scroll" : "1m", 
 "scroll_id" : "c2Nhbjs2OzM0NDg1ODpzRlBLc0FXNlNyNm5JWUc1" 
````


或许经过search lite api的办法:

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


这样顺次循环读取直到searchHits数组为空的情况下就代表数据读取结束。





同理聚合的scroll恳求,也是如此,但聚合恳求的数据体只会在初始化的search里边存在,这一点需求留意,不过聚合恳求的scroll一般没有这种运用场景,究竟聚合后的成果一般都是少了好几个数量级的。



此外scroll恳求还能够增加一个或多个排序字段,假如你读取的索引数据彻底疏忽它的次序,那么咱们还能够运用doc字段排序来提高功能。

````
curl -XGET localhost:9200/_search?scroll=1m -d 
 "sort": [
 "_doc"
````



ok,再弥补下再java api里边怎么全量读取es索引数据的办法:

````
` //指定一个index和type 
 SearchRequestBuilder search = client.prepareSearch("active2018").setTypes("active");
 //运用原生排序优化功能
 search.addSort("_doc", SortOrder.ASC);
 //设置每批读取的数据量
 search.setSize(100);
 //默许是查询一切
 search.setQuery(QueryBuilders.queryStringQuery("*:*"));
 //设置 search context 保护1分钟的有效期
 search.setScroll(TimeValue.timeValueMinutes(1));
 //取得初次的查询成果
 SearchResponse scrollResp=search.get();
 //打印射中数量
 System.out.println("射中总数量:"+scrollResp.getHits().getTotalHits());
 //打印计数
 int count=1;
 do {
 System.out.println("第"+count+"次打印数据:");
 //读取成果集数据
 for (SearchHit hit : scrollResp.getHits().getHits()) {
 System.out.println(hit.getSource()) ;
 count++;
 //将scorllId循环传递
 scrollResp = client.prepareSearchScroll(scrollResp.getScrollId()).setScroll(TimeValue.timeValueMinutes(1)).execute().actionGet();
 //当searchHits的数组为空的时分结束循环,至此数据悉数读取结束
 } while(scrollResp.getHits().getHits().length != 0); 
````





### (三)删去无用的scroll



上文说到scroll恳求时会保护一个search context快照集,这是怎么做到的? 经过前面的几篇文章(点底部菜单栏能够看到),咱们知道es在写入数据时,会在内存中不断的生成segment,然后有一个merge线程,会不断的兼并小segment到更大的segment里边,然后再删去旧的segment,来削减es对体系资源的占用, 尤其是文件句柄,那么保护一个时刻段内的索引快照,则意味着这段时刻内的一切segment不能被兼并,不然就破坏了快照的静态性,这样以来暂时不能被兼并的小segment会占体系很多的文件句柄和体系资源,所以scroll的办法一定是离线运用的而不是供给给近实时运用的。

咱们需求养成一个好习惯,当咱们用完之后应该手动铲除scroll,尽管search context超时也会主动铲除。


es中供给了能够检查当时体系中有多少个open search context的api指令:

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




下面看下删去scrollId的办法

(1)删去一个scrollId

````
DELETE /_search/scroll
 "scroll_id" : "UQlNsdDcwakFMNjU1QQ=="
````


(2)删去多个scrollId

````
DELETE /_search/scroll
 "scroll_id" : [
 "aNmRMaUhiQlZkMWFB==",
 "qNmRMaUhiQlZkMWFB=="                          
			
版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表牛牛娱乐立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章

阅读排行

  • 1

    java多线程(七)ITeye

    线程,倾向,目标
  • 2

    java线程池ITeye

    线程,使命,工人
  • 3
  • 4
  • 5

    修饰符ITeye

    润饰,能够,直接
  • 6
  • 7
  • 8

    第02章 根底中心ITeye

    目标,根底,中心
  • 9
  • 10