MongoDB: уменьшить размер чтения и оперативную память, необходимые с проектом? - PullRequest
1 голос
/ 23 апреля 2020

Я проектирую базу данных MongoDB, которая выглядит примерно так:

registry:{
id:1,
duration:123,
score:3,
text:"aaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}  

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

db.registries.aggregate( [
  {
    $group: {
       _id: null,
       averageDuration: { $avg: "$duration" },
    }
  }
] )

Нужно ли будет читать данные из поля расшифровки? Это сделает запрос намного медленнее и потребует много оперативной памяти. Если это так, то было бы лучше разделить записи на две части и получить что-то вроде этого, верно?:

registry:{
id:1,
duration:123,
score:3,
}  


registry_text:{
id:1,
text:"aaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}  

Большое спасибо!

Ответы [ 3 ]

2 голосов
/ 24 апреля 2020

Я не знаю, как работает сервер в этом случае, но я ожидаю, что по причинам кэширования сервер будет загружать полные документы в память при чтении их с диска. Чтение с диска происходит очень медленно (= требует много времени), и я ожидаю, что сервер будет активно использовать память, если сможет избежать чтения.

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

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

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

Я думаю, что это не так Не стоит пытаться обдумывать / оптимизировать. Если у вас есть реальная система с реальными рабочими нагрузками, вам будет гораздо сложнее оптимизировать что-то еще.

Если вы беспокоитесь об использовании памяти, когда объем доступной памяти имеет размер потребителя (скажем, до 16 gb), просто получите больше памяти - это безумно дешево, учитывая, сколько времени вы бы потратили на работу из-за ее нехватки (говорим ли мы о предоставлении больших экземпляров AWS или покупке большего количества оперативной памяти).

1 голос
/ 23 апреля 2020

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

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

https://dba.stackexchange.com/questions/198444/how-mongodb-projection-affects-performance

1 голос
/ 23 апреля 2020

Вы должны иметь возможность использовать $project, чтобы ограничить поля, которые читаются.

В качестве общего совета, не пытайтесь нормализовать данные с MongoDB, как это было бы с SQL. Кроме того, часто более эффективно читать документы в простом виде из БД и выполнять обработку на вашем сервере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...