Захват неизвестного документа, добавленного во время большого запроса на поиск в Mongodb

Мне было интересно, Spring Mongo API для find загружает все в файл List. Если результат поиска содержит миллиард записей, не повлияет ли это на память? Может ли кто-нибудь предложить лучший способ добиться этого, не загружая все это в память. Использование limit может помочь, но тогда есть недостаток, который заключается в том, что он не узнает, вставлен ли новый документ в коллекцию. Что ж, поиск по лимиту имел бы тот же эффект, если бы коллекция изменилась после чтения X of billion записей.

Итак два вопроса:

  • Повысьте производительность, не загружая все в память
  • Как бы вы решили этот неизвестный документ, добавленный во время обработки?

Код из API

List<T> result = new ArrayList<T>();

while (cursor.hasNext()) {
    DBObject object = cursor.next();
    result.add(objectCallback.doWith(object));
}

person java_dude    schedule 22.03.2015    source источник


Ответы (1)


Повысьте производительность, не загружая все в память

Соответствующий пользовательский интерфейс для результатов поиска обычно имеет ограничение на количество результатов, которые необходимо отобразить (например, результаты на странице, а также общие результаты). Я не думаю, что есть какой-либо разумный вариант использования для загрузки неограниченного набора результатов в память, но хорошей гарантией было бы включение разумного ограничения в запросы вашего приложения.

Сервер MongoDB возвращает результаты запроса в виде пакетов курсоров, которые не могут превышать максимальный размер документа BSON (16 МБ, как в MongoDB 3.0 . .и на самом деле обычно 1 МБ для первой партии и 4 МБ для последующих партий). Вы можете получить более крупный результат, продолжая итерировать курсор в коде приложения, но реализация — это ваш выбор.

Как бы вы решили этот неизвестный документ, добавленный во время обработки?

Упорядочивайте результаты поиска по свойству новых документов, которое монотонно увеличивается, например, по сгенерированному по умолчанию ObjectId. Курсоры (как в MongoDB 3.0) не обеспечивают изоляцию от операций записи, поэтому документы, которые вставляются или обновляются во время обработки, также будут включены, если это применимо к порядку запроса.

Если ваш код повторяет большой запрос, отсортированный по _id (по возрастанию), новые документы, вставленные с использованием ObjectId по умолчанию, должны появиться в последних пакетах.

person Stennie    schedule 24.06.2015
comment
Это реальный вариант использования. В Expedia (вашем клиенте) наша группа также является держателем данных. Любая группа может запросить у нас все данные с начала времени. Мы рекомендуем получать данные каждый месяц, но может быть случай, когда группа просто захочет начать заново. Эти группы анализируют исторические данные. Таким образом, это было решено с использованием лимита корзины в 100 000 записей. - person java_dude; 24.06.2015
comment
Который, я полагаю, передавал 7-10 миллионов записей менее чем за 25 минут между двумя разными центрами обработки данных в двух разных местах. Таким образом, вопрос теперь больше о том, как получить новый документ или обновленный документ, который произошел между 25 минутами. Я могу получить новые данные по сортировке _id, но как быть с обновлениями? Должен ли я включать сортировку по update? - person java_dude; 24.06.2015
comment
@java_dude В вашем исходном вопросе упоминалось только об обнаружении новых документов, вставляемых при повторении большого запроса; обновления должны обрабатываться по-другому. Вы можете использовать дозорное значение с отметкой времени (например, дата последнего изменения в документах) или настроить процесс для хвоста оплогов для измененных документов на основе пространства имен и фильтра запроса. В зависимости от вашей модели данных могут быть более эффективные варианты, но это более длинное обсуждение, чем в комментариях здесь :). - person Stennie; 24.06.2015
comment
Я согласен, что это еще одно обсуждение, и я ценю ваш ответ. - person java_dude; 24.06.2015