elasticsearch 大資料場景下使用scroll實現分頁查詢
阿新 • • 發佈:2018-11-05
es查詢大批量資料的”可能方案”
當使用es來請求大批量資料時,通常有三種辦法,其一:直接查詢獲取全量資料;其二:使用setFrom以及setSize解決;其三:使用es自帶的scroll分頁支援
方案評估
對於上述方案的評估,此處建議大家可以先看看這篇文章 Elasticsearch 搜尋內部執行原理
方案選擇
經上述評估,顯然,最終採取scroll進行分頁實現,分頁後的資料處理有兩種方式可供處理。第一種,獲取分頁後的資料再聚合;第二種,直接處理分頁後的資料。對於第一種,如若聚合後的資料有幾十萬、上百萬,乃至更多,那勢必會導致系統記憶體飆升,jvm老年代可能會被迅速打滿,進而促發full gc, 若full gc後仍得不到可用空間,可能會造成oom,服務直接不可用。所以第一種處理方式是存在風險的,推薦使用第二種
核心程式碼
假定各位maven已配置好,es處於可用狀態
使用scroll分頁主要分為2步,第1步,初始化查詢,獲取scrollId。第2步使用scrollId迭代查詢
- 初始化查詢
//構建查詢條件(非必須)
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.matchQuery("rate_object","item"));
RangeQueryBuilder publishDateBuilder = QueryBuilders.rangeQuery ("created_at");
publishDateBuilder.from("2018-04-22 00:00:00");//格式需要同你建立索引時的格式匹配
boolQueryBuilder.filter(publishDateBuilder);
TransportClient client = factory.getClient();
SearchResponse response = client.prepareSearch("index")//對應索引
.setTypes("type")//對應索引type
.setQuery (boolQueryBuilder)
.setScroll(TimeValue.timeValueMinutes(10))
.setSize(100)
.execute()
.actionGet();
- 迭代查詢
//此處實現迭代的方式較多,僅列其一,
while (response.getHits().getHits().length>0) {
String scrollId = response.getScrollId();
response = client.prepareSearchScroll(scrollId)
.setScroll(TimeValue.timeValueMinutes(10))//設定查詢context的存活時間
.execute()
.actionGet();
SearchHits hits = response.getHits();
for (SearchHit hit:hits.getHits()) {
String hitString = hit.getSourceAsString();
System.out.println(hitString);//此處可進行業務邏輯
}
}
注:處理結束後,記得clean scroll
ClearScrollRequest request = new ClearScrollRequest();
request.addScrollId(response.getScrollId());
client.clearScroll(request);
留下此篇部落格以供自己日後參考