Уменьшает ли агрегация MongoDB $ project объем данных, сохраняемых в памяти? - PullRequest
0 голосов
/ 11 января 2020

Мне интересно, действительно ли запись $project сразу после оператора $match уменьшает объем данных, которые должны храниться в памяти. Например, если нам нужен элемент массива с подкачкой из пользовательского документа, например:

const skip = 20;
const limit = 50;

UserModel.aggregate([
            { $match: { _id: userId } },
            { $project: { _id: 0, postList: 1 } },
            { $slice: ["$postList", skip, limit] },
            { $lookup: ...
]);

Предположим, что в пользовательском документе есть другие списки, и они очень большого размера.

Итак, $project поможет улучшить производительность, не занимая другие большие списки в памяти?

1 Ответ

1 голос
/ 13 января 2020

Каждый этап агрегирования сканирует входные документы из коллекции (если это первый этап) или предыдущего этапа. Например,

  • match (фильтрует документы) - это уменьшит количество документов, общий размер
  • проекта (преобразует или формирует документ) - это может уменьшить (или увеличить) размер документа; количество документов остается неизменным
  • группа - уменьшает количество документов и изменяет размер
  • пропустить, лимит - уменьшить количество документов
  • сортировать - без изменений в размер или количество документов и т. д. c.

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

Ограничения памяти для агрегации уже четко определены в документации (см. Ограничения конвейерного агрегирования ). Если предел памяти превышает ограничения, агрегация прекратится. В таких случаях вы можете указать параметр агрегирования { allowDiskuse: true }, и использование этого параметра повлияет на производительность запроса. Если ваша агрегация работает без каких-либо проблем, связанных с памятью (например, завершение запроса из-за превышения пределов памяти), тогда нет никаких проблем с производительностью запроса напрямую.

Этапы $match и $sort используют индексы, если они используются в начале конвейера. И это может повысить производительность.

Добавление этапа в конвейер означает дополнительную обработку и может повлиять на общую производительность. Это связано с тем, что документы предыдущего этапа должны пройти этот дополнительный этап. В конвейере агрегации документы проходят через каждый этап - как в конвейере, и этап выполняет некоторую трансформацию данных. Если вы можете избежать этапа, это может иногда повысить общую производительность запросов. Когда числа большие, наличие лишнего (ненужного) этапа, безусловно, является недостатком. Необходимо учитывать как ограничения памяти, так и размер и количество документов.

A $project может использоваться для уменьшения размера документа. Но нужно ли добавлять этот этап? Это зависит от факторов, которые я упомянул выше, от вашей реализации и приложения. Документация ( Projection Optimization ) гласит:

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

...