Увеличение лимита памяти для агрегатных заданий mongodb

Согласно документам конвейера агрегации, «любая отдельная операция агрегации потребляет более 10 процентов оперативной памяти системы, операция приведет к ошибке». - http://docs.mongodb.org/manual/core/aggregation-pipeline-limits/

Есть ли способ увеличить этот лимит? Я также установил allowDiskUse: true (поэтому ошибка больше не является проблемой), но хотел бы использовать больше оперативной памяти для повышения производительности.

Справочная информация. Я выполняю большую совокупную работу в mongodb с примерно 100 миллионами записей. По сути, это массовый вызов $group для объединения записей на основе ключа.

Я использую версию mongo v 2.6.0-rc2 для разработчиков (21 марта 2014 г.)


person Jeff Tsui    schedule 29.03.2014    source источник
comment
Я не верю, что в настоящее время вы можете попробовать записать в коллекцию, которая может обмануть лимит   -  person Sammaye    schedule 29.03.2014


Ответы (2)


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

Вот что "должно" быть в "голове" любого разумного конвейера агрегации:

db.collection.aggregate([
    { "$match:{ /* Something here */ } },

А это причины:

  1. Разумно попытаться уменьшить рабочий набор, с которым вы работаете, в любой операции.

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

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

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

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

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

С точки зрения "программирования в соответствии с требованиями к оборудованию", вы знаете, что будущие выпуски позволяют конвейеру агрегации реализовывать "использование диска" для увеличения объема обработки. Вы всегда можете использовать SSD или другие быстрые технологии хранения. И, конечно же, "10%" оперативной памяти зависит от объема оперативной памяти, установленной в системе. Так что вы всегда можете увеличить это значение.

Суть в том, что MongoDB выполняет работу как "параллельное хранилище данных" и делает это хорошо. То, что не является, является конкретным "агрегированием job-runner" и не должно рассматриваться как таковое.

Так что либо "разбейте" ваши рабочие нагрузки, либо увеличьте спецификации вашего оборудования, либо просто переключите большую активность "запуска задачи" на что-то, что делает сосредоточьтесь на текущей задаче, такой как mapReduce в стиле Hadoop, и предоставьте MongoDB ее работу по обслуживанию данных.

Или, конечно, измените свой дизайн, чтобы просто "предварительно агрегировать" необходимые данные где-нибудь "при записи".

Как говорится, «Лошади для курсов» или используйте свои инструменты для того, для чего они разработаны.

person Neil Lunn    schedule 29.03.2014
comment
Для меня этот лимит памяти весьма условен и мешает. Я запускаю агрегацию в БД с большим количеством документов (ожидается рост до ~ 450 миллионов), и мне приходится регулярно выполнять запросы, которые возвращают несколько миллионов документов. Это потребляет около 8 ГБ оперативной памяти для запуска, поэтому 100 МБ слишком мало и на самом деле просто произвольное значение. - person Emanuel Ey; 23.04.2015
comment
Пожалуйста, сэр, полегче с акцентами. Этот иначе хорошо ответ больно my *глаза* ;) - person Madbreaks; 18.12.2019
comment
Хотя я согласен с тем, что у каждого инструмента есть своя функция, 100 МБ действительно случайны и в некоторых случаях слишком малы (почему 100, а не 90? Почему 100, а не 200? каждая система отличается). Не вижу особых причин не позволять кому-то регулировать лимит под свои нужды. Если есть момент, когда это может повредить другим функциям монго (не понимаю, почему это должно быть, но давайте учтем это), это можно указать в спецификациях. Вы можете установить диск в ОЗУ и использовать его, или вы можете использовать более быстрые твердотельные накопители (которые в любом случае не будут приближаться к скорости оперативной памяти). Но зачем быть вынужденным это делать? - person zozo; 06.10.2020

Я могу придумать 3 решения:

Решение 1 (Mongodb): $sort по идентификатору . Используйте $group только для подсчета количества документов на уникальный идентификатор. Затем используйте $facet с $limit и $skip, чтобы разделить операцию. Я этого не делал, но собираюсь попробовать, так как у меня та же проблема, что и у вас.

Решение 1 (Mongodb). В зависимости от запросов вашего варианта использования и количества различных идентификаторов вы можете создать коллекцию для каждого идентификатора. Это некрасиво, но если каждый запрос нацелен только на определенный идентификатор, это может иметь смысл. Особенно при небольшом количестве идентификаторов может не быть другого обходного пути, поскольку существует жесткое ограничение на размер документа (я думаю, 16 МБ). Я полагаю, что достаточно большой массив документов, вложенный в документ, не вариант.

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

Выполнение большинства операций с памятью за миллисекунды.

Если данные слишком велики, чтобы хранить их в памяти в течение всей операции, вы можете сопоставить файлы с памятью и использовать представления этих сопоставленных файлов. Я использую 2 небольших NVME в другом проекте, каждый из которых стоит 40 евро. Вместе они могут записать 15 ГБ на диск менее чем за 3 секунды, что соответствует размеру буфера, который мне нужен для всего набора данных.

Друг убедил меня попробовать mongodb, чтобы очистить сильно меняющиеся данные, и в настоящее время я обрабатываю коллекцию размером 200 МБ, которая в конечном итоге вырастет до 100 раз больше. Операция, которую я выполняю, — это просто группировка документов по идентификатору и помещение корней в массив. Для параметра Allowdiskuse установлено значение true, но, кроме формулировки сообщения об ошибке, это не имеет значения.

Я действительно не вижу проблемы в том, чтобы позволить пользователю настроить ограничение памяти в соответствии со своими потребностями. Даже если люди скажут, что использование 16 ГБ памяти — плохая идея, существует множество сценариев, в которых это точно не так. Мы, взрослые, должны иметь право совершать собственные ошибки. Ни одна операция с базой данных размером 200 МБ никогда не должна быть проблемой, особенно такая простая, как та, которую я выполняю или не могу выполнить.

person seafunk    schedule 01.03.2021