Нормализация данных, то есть разбиение информации по нескольким связанным таблицам или коллекциям, неэффективна в распределенной среде. В классических реляционных СУБД нормализация помогает избежать дублирования данных, но в MongoDB, особенно при масштабировании, каждый дополнительный JOIN становится дорогой операцией. MongoDB работает по документной модели, поэтому лучше проектировать данные так, чтобы все необходимое для одного запроса было в одном документе - это упрощает доступ и повышает производительность
Поэтому в MongoDB существуют 2 подхода хранения данных: встраивание (embedded) и ссылки (reference)
При встраивании один документ встраивается в другой, например, адрес с именем города и улицы внутри пользователя. Встраивание можно использовать:
Ссылка представляет собой идентификатор на другой документ в базе. В этом случае данные хранятся в отдельных коллекциях, и может понадобиться выполнять два запроса или использовать $lookup
, чтобы получить связанные данные. Ссылку следует использовать:
Oplog (от Operation Log, операционный журнал) - специальная коллекция, которая фиксирует все изменения, происходящие в основной базе данных. Используется в репликации, чтобы вторичные узлы могли синхронизировать изменения с основного. Благодаря этому достигается асинхронная репликация и высокая отказоустойчивость
mongosh
- это интерактивная оболочка командной строки для работы с MongoDB. Она построена на движке V8 (тот же, что используется в Google Chrome), поэтому поддерживает современный JavaScript-синтаксис (ES6): стрелочные функции, let/const
, деструктуризацию, промисы и т.д.
Пример вставки одного документа:
db.users.insertOne({ name: "Alice", age: 30 });
db.users.deleteMany({ age: { $lt: 18 } });
MongoDB поддерживает множество операторов ($set
, $inc
, $push
, $pull
, $addToSet
, $elemMatch
и др.), которые позволяют модифицировать данные без полной перезаписи документа. Это важно для производительности и экономии трафика
Репликация - это механизм, позволяющий автоматически копировать данные с основного узла на один или несколько вторичных узлов. В случае сбоя первичного узла происходит автоматическое переключение лидерства (failover), и один из вторичных становится новым первичным. Репликация в MongoDB идет прямо из коробки, в отличие от PostgreSQL
Также MongoDB поддерживает BSON (Binary JSON) - двоичный формат сериализации данных. Он похож на JSON, но включает дополнительные типы данных (например, Date
, BinData
, ObjectId
), поддерживает более быструю обработку и позволяет задавать структуру данных компактно и эффективно
MongoDB поддерживает разные движки хранения:
WiredTiger - основной современный движок (по умолчанию). Он поддерживает:
MongoDB гарантирует атомарность операций на уровне одного документа. Это означает, что все изменения, сделанные в одном документе (включая вложенные поля и массивы), происходят либо полностью, либо не происходят вообще
Многодокументная атомарность возможна только с использованием транзакций (начиная с MongoDB 4.0). Но такие транзакции имеют накладные расходы и используются лишь тогда, когда без них нельзя обойтись
В распределенной базе данных на основе MongoDB есть параметры надежности чтения и записи
“Read Concern” (надежность чтения) определяет, насколько актуальными и подтвержденными должны быть читаемые данные:
local
- прочитать данные с текущего узла без ожидания подтверждения (самый быстрый, но наименее надежный)majority
- только те данные, которые подтверждены большинством узловsnapshot
- используется в транзакциях, обеспечивает согласованную точку во времени“Write Concern” (надежность записи) определяет, сколько узлов должно подтвердить запись:
{ w: 1 }
- запись подтверждается только первичным{ w: "majority" }
- запись подтверждается большинством узлов{ w: 0 }
- запись не требует подтверждения (максимальная скорость, но нет гарантии сохранения)В MongoDB:
Индексы ускоряют поиск, сортировку, агрегации и обеспечивают уникальность данных, но занимают память и замедляют вставку/обновление
Оператор $lookup
позволяет делать аналог JOIN в MongoDB
Шардинг - это механизм горизонтального масштабирования, при котором данные автоматически распределяются по нескольким узлам (шардам). До версии 4.4 MongoDB не поддерживал JOIN между двумя шардами. Начиная с MongoDB 4.4, стало возможно использовать $lookup
, даже если обе участвующие коллекции находятся в шардах
MongoDB позволяет анализировать производительность запросов с помощью:
explain()
- показывает, как будет выполняться запрос (используются ли индексы, какой путь обхода)db.setProfilingLevel()
) - позволяет логировать медленные запросы и анализировать поведение БД в реальном времениТипы планов в explain:
COLLSCAN
- полный скан коллекции (медленно)IXSCAN
- использование индекса (гораздо быстрее)IDHACK
- быстрый доступ по _id