滚动成功完成,无需滚动浏览 ES 中的所有记录



>我有一个基于这些文档摘录的滚动:

SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withIndices(INDEX_NAME)
.withTypes(TYPE_NAME)
.withFields("message")
.withPageable(PageRequest.of(0, 10))
.build();
Page<SampleEntity> scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class);
String scrollId = ((ScrolledPage) scroll).getScrollId();
List<SampleEntity> sampleEntities = new ArrayList<>();
while (scroll.hasContent()) {
sampleEntities.addAll(scroll.getContent());
scrollId = ((ScrolledPage) scroll).getScrollId();
scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class);
}
elasticsearchTemplate.clearScroll(scrollId);

我需要滚动浏览一个巨大的数据集(超过 100 密耳)。

我的卷轴看起来与此摘录完全相同(只有我的查询和对象)。 但是在startScroll和contrinueScroll中,我传递了一个不同的自定义文档类,该类的字段比用于索引的文档少得多,但是我的查询具有过滤器,因此仅返回与用于滚动的另一个文档匹配的几个字段。

getTotalElements()滚动方法返回要获取的所有元素的正确数量。

滚动循环成功完成,但它仅滚动浏览数据集的 6%。

不是一个真正的解决方案,但看看你的代码,你正在构建一个最终将包含所有SampleEntityList<SampleEntity>。如果其中一个实体仅使用 256 个字节,超过 100mil,则至少为 25GB 内存。您有多少可用内存?

至于服务器日志:根据垃圾收集消息,Elasticsearch似乎也用尽了它所有的内存。您在这些计算机上配置了什么?

编辑25.07.2020

我已经设置了一个具有以下设置的测试程序:

  • 本地 Elasticsearch 6.4.2
  • 使用传输客户端的 Spring 数据弹性搜索 3.1.0

我创建了一个包含 2500 万个条目的索引,一个是长 ID 的对象,一个是字符串。这给 ES 在垃圾收集方面带来了一些压力,但已完成。

使用 matchAll 查询和大小为 1000 的可分页读取所有条目(不是聚合列表中的结果,而是计算返回的记录)运行没有问题。

在请求中使用任何可分页的内容(导致每个滚动请求的请求大小为 10 个)会给 Elasticsearch 带来沉重的负担,甚至会给客户端进程带来更多负担。但是这个请求也没有问题,尽管运行非常慢。这会在 Elasticsearch 和客户端程序中创建大量垃圾回收。

所以看起来代码是正确的,问题在于页面大小,默认值 10 太少了,我成功运行了它,最多 10000(这是您可以在不增加index.max_result_window的情况下使用的最大值)。

因此,您可以尝试增加可分页的大小,但请记住,收集所有这些元素会给应用程序的内存消耗带来沉重的负担。

最新更新