Из MongoDB
документации упоминается, что:
Когда вам нужно только подмножество полей из документов, вы можете добиться лучшей производительности, возвращая только те поля, которые вам нужны
Как поля фильтрации влияют на производительность? Связана ли производительность с размером данных, передаваемых по сети? или размер данных, которые будут храниться в памяти? Как именно эта производительность улучшается? Что это за производительность, упомянутая в документации?
У меня медленные запросы MongoDB. Влияет ли возвращаемое подмножество на мой медленный запрос (у меня есть составной индекс на поле)?
Debian 8
,MongoDB 3.6.2
Ответы:
По умолчанию запросы возвращают все поля в соответствующих документах. Если вам нужны все поля, возврат полных документов будет более эффективен, чем когда сервер манипулирует результирующим набором с помощью критериев проекции.
Однако использование проекции для ограничения полей для возврата из результатов запроса может повысить производительность за счет:
При использовании проекции для удаления неиспользуемых полей серверу MongoDB придется извлекать каждый полный документ в память (если его там еще нет) и фильтровать результаты для возврата. Такое использование проекции не уменьшает использование памяти или рабочего набора на сервере MongoDB, но может сэкономить значительную пропускную способность сети для результатов запроса в зависимости от модели данных и проецируемых полей.
Закрытый запрос - это особый случай, когда все запрошенные поля в результате запроса включены в используемый индекс, поэтому серверу не нужно извлекать полный документ. Покрываемые запросы могут повысить производительность (исключая выборку документов) и использование памяти (если другие запросы не требуют выборки того же документа).
Примеры
Для демонстрации с помощью
mongo
оболочки представьте, что у вас есть документ, который выглядит следующим образом:Поле
b
может представлять выбор значений (или в этом случае очень длинную строку).Затем создайте индекс, по
{a:1}
которому часто используется поле, запрашиваемое вашим вариантом использования:Простой
findOne()
без критериев проекции возвращает результат запроса, который составляет около 10 МБ:Добавление проекции
{a:1}
ограничит вывод в полеa
и документ_id
(который включен по умолчанию). Сервер MongoDB по-прежнему манипулирует документом 10 МБ для выбора двух полей, но результат запроса теперь составляет всего 33 байта:Этот запрос не покрыт, потому что полный документ должен быть выбран, чтобы обнаружить
_id
значение._id
Поле включено в результатах запроса по умолчанию , так как он является уникальным идентификатором для документа, но_id
не будет включен в вторичном индексе , если явно не добавлено.totalDocsExamined
ИtotalKeysExamined
метрики вexplain()
результатах будет показано , сколько документов и ключи индекса были рассмотрены:Этот запрос можно улучшить с помощью проекции, чтобы исключить
_id
поле и выполнить покрытый запрос, используя только{a:1}
индекс. Покрываемому запросу больше не нужно извлекать документ размером ~ 10 МБ в память, поэтому он будет эффективен как по сети, так и по использованию памяти:Это не подлежит ответственности без контекста конкретного запроса, примера документа и полного вывода объяснения. Тем не менее, вы можете запустить некоторые тесты в своей среде для одного и того же запроса с прогнозом и без него, чтобы сравнить результат. Если ваш прогноз добавляет значительные накладные расходы к общему времени выполнения запроса (обработка и передача результатов), это может быть сильным намеком на то, что ваша модель данных может быть улучшена.
Если неясно, почему запрос медленный, было бы лучше опубликовать новый вопрос с конкретными деталями для расследования.
источник
С помощью проекции вы можете получить ситуацию, когда набор результатов будет получен непосредственно из индекса.
Если у вас есть составной индекс,
{x:1, y:1, z:1}
где ни один из x, y, z не равен _id, вам необходимо спроецировать,{_id:0, x:1, y:1, z:1}
потому что_id
он всегда возвращается как часть набора результатов (когда он не спроецирован), и движок должен читать файлы данных, чтобы получить его. Это потому, что индекс не имеет значения _id, только указатель на тот документ, где хранится значение.источник
_id
из возвращенного ответа, это помещается в RAM? Это помогает?_id:0
то результат возвращается полностью из ОЗУ, без чтения данных с диска.