Прокрутка завершается успешно без прокрутки всех записей в ES - PullRequest
0 голосов
/ 14 июля 2020

У меня есть свиток, основанный на выдержке из этих документов :

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() Метод scroll возвращает правильное количество всех элементов для выборки.

Прокрутка l oop завершается успешно, но прокручивается только через 6% набора данных.

1 Ответ

1 голос
/ 20 июля 2020

Не настоящее решение, но, глядя на ваш код, вы создаете List<SampleEntity>, который в конечном итоге будет содержать все ваши SampleEntity s. Если один из этих объектов использует только 256 байт, более 100 мил, это будет минимум 25 ГБ памяти. Сколько памяти у вас доступно?

Что касается журналов сервера: Судя по сообщениям о сборке мусора, похоже, что Elasticsearch также использует всю свою память. Что вы настроили на этих машинах?

Изменить 25.07.2020 :

Я установил тестовую программу со следующей настройкой:

  • local Elasticsearch 6.4.2
  • Spring Data Elasticsearch 3.1.0 с использованием транспортного клиента

Я создал индекс с 25 миллионами записей, объектами с длинным идентификатором и одним uuid как Строка. Это создало некоторую нагрузку на ES в отношении сборки мусора, но завершилось.

Чтение всех записей (не агрегирование результатов в списке, а подсчет возвращенных записей) с запросом matchAll и запуском страницы размером 1000 без проблем.

Использование в запросе без страницы (в результате размер запроса составляет 10 на запрос прокрутки) создает большую нагрузку на Elasticsearch и даже больше на клиентский процесс. Но и этот запрос завершился без проблем, хотя выполнялся очень, очень и очень медленно. Это создает тяжелые сборки мусора как в Elasticsearch, так и в клиентской программе.

Кажется, что код правильный, проблема заключается в размере страницы, значение по умолчанию 10 слишком мало, я успешно выполнил его до 10000 (это максимум, который вы можете использовать без увеличения index.max_result_window).

Таким образом, вы можете попытаться увеличить размер страницы, но имейте в виду, что сбор всех этих элементов создает тяжелую нагрузка на потребление памяти вашим приложением.

...