17.es 深度翻页

2021-05-25  本文已影响0人  不怕天黑_0819

本文集主要是总结自己在项目中使用ES 的经验教训,包括各种实战和调优。

index.max_result_window 通过在yml文件中修改这个配置可以调整最大查询数(强烈不建议修改)

es默认只能查询10000条数据,那么针对深度翻页,根据官网的示例,主要有两种方式。scroll和search after。

两种方式的优缺点:the Scroll api is recommended for efficient deep scrolling but scroll contexts are costly and it is not recommended to use it for real time user requests. The search_after parameter circumvents this problem by providing a live cursor. The idea is to use the results from the previous page to help the retrieval of the next page.

总的来说,Scroll实现简单,但是性能花费较大,不适合于实时用户请求。search after实现原理类似于通过上一页的数据来获取下一页的数据。

但是应该避免深度翻页的,对性能损耗较大,

CPU、内存和IO消耗容易理解,网络带宽问题稍难理解一点。在 query 阶段,每个shards需要返回 1,000,100 条数据给 coordinating node,而 coordinating node 需要接收 10 * 1,000,100 条数据,即使每条数据只有 _doc _id 和 _score,这数据量也很大了,而且,这才一个查询请求,那如果再乘以100呢?

深度翻页的应用场景

这种深度分页的需求确实存在,比如,被爬虫了,这个时候,直接干掉深度分页就好;又或者,业务上有遍历数据的需要,比如,有1千万粉丝的微信大V,要给所有粉丝群发消息,或者给某省粉丝群发,这时候就需要取得所有符合条件的粉丝,而最容易想到的就是利用 from + size 来实现,不过,这个是不现实的,这时就需要深度翻页。

1.Scroll

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/5.3/search-request-scroll.html 可以通过response.getHits().getHitAt(i) 来获取指定数据

如果不要求顺序,可以使用Scroll-Scan

SearchResponse response = clientOnline.prepareSearch("subscribe_content_manage").setTypes("content_manage_info")

.setScroll(new TimeValue(60000)).setQuery(query).setSize(1000).execute().actionGet();

do {

for (SearchHit searchHit : response.getHits().getHits()) {//这里的for循环次数==size

i++;

hitMap = searchHit.getSource();

articleSyncService.test(hitMap.get("articleId").toString());

}

response = clientOnline.prepareSearchScroll(response.getScrollId()).setScroll(new TimeValue(60000)).execute().actionGet();

} while (response.getHits().getHits().length != 0);

boolean clearScroll = clearScroll(response.getScrollId());

if (!clearScroll){

log.warn("clear scroll id false,scrollId:"+response.getScrollId());

}

2.search after

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/5.3/search-request-search-after.html

GET subscribe_content_manage/content_manage_info/_search
{
"size": 1000,
"query": {
"match_all": {}
},
"search_after": [ "content_manage_info#C8E1RAGK0521807P",1481907301000],
"sort": [
{"_uid": "desc"},
{"updateTime": "asc"}
]
}

上面是kibana使用的实现范例,java代码的没有实践,但是原理是一样的,另外文档建议,使用uid这一类的唯一id也作为排序规则之一,避免相同的排序值无法确定具体的文档。通过传入上一页的排序值来获取下一页的数据。search after不是用来解决随机跳转的,搜索参数也是无状态的。

关于scroll 深度翻页的笔记:

使用scroll实现Elasticsearch数据遍历和深度分页

上一篇 下一篇

猜你喜欢

热点阅读