Разработчик и сотрудник проекта CouldBoost.io Наваз Дандала (Nawaz Dhandala) написал материал о том, почему в некоторых случаях не стоит использовать MongoDB. Мы в «Латере» развиваем биллинг для операторов связи «Гидра» и уже много лет работаем с этой СУБД, поэтому решили представить и свое мнение по данному вопросу.
Дандала сразу оговаривается, что работал со многими СУБД (как SQL, так и NoSQL) и считает MongoDB отличным инструментом, однако существуют сценарии, в которых его применение нецелесообразно.
Документоориентированные СУБД такие, как MongoDB, прекрасно справляются с хранением JSON-данных, сгруппированных в «коллекции». В таком формате можно хранить любые JSON-документы и удобно категоризировать и по коллекциям. Содержащийся в MongoDB JSON-документ называется двоичным JSON или BSON и, как любой другой документ этого формата, является неструктурированным. Поэтому, в отличии от традиционных СУБД, в коллекциях можно сохранять любые виды данных, и эта гибкость сочетается с горизонтальной масштабируемостью базы данных. Эта возможность нравится многим разработчикам, однако «не все так однозначно».
Если MongoDB такая классная, почему ее не используют все и всегда?
Выбор СУБД зависит в том числе и от того, что за приложение планируется создать. То есть базу данных выбирают не разработчики, а сам продукт, убежден Дандала. Он приводит пример, подтверждающий этот тезис.
При создании приложения, концепция которого подразумевает работу с документами, MongoDB будет хорошим выбором. К такому типу приложений можно отнести, к примеру, движок блог-платформы, где каждый автор сможет иметь по несколько блогов, и каждый из них будет содержать множество комментариев. База данных для обслуживания такого приложения должна быть легко расширяемой, и здесь MongoDB подойдет как рельзя лучше.
Однако, необходимо отметить, что у MongoDB нет связей между документами и “коллекциями” (частично это компенсируется Database Reference — ссылками в СУБД, но это не полностью решает проблему). В итоге, возникает ситуация, при которой имеется некий набор данных, который никак не связан с другой информацией в базе, и не существует никакого способа объединить данные из различных документов. В SQL-системах это было бы элементарной задачей.
Здесь возникает другой вопрос — если в MongoDB нет связей и возможностей по объединению двух таблиц, то зачем ее тогда вообще использовать? Ответ — потому что эта СУБД отлично масштабируется, и по сравнению с традиционными SQL-системами, гораздо быстрее осуществляет чтение и запись.MongoDB прекрасно подходит для приложений, в которых практически не используются данные с зависимостями и необходима масштабируемость базы данных.
Многие разработчики применяют MongoDB и для хранения связанных данных, реализуя объединения вручную в коде — этого достаточно в сценариях «одноуровневого» объединения или малого количества связей. То есть данный метод далеко не универсален.
Так какую СУБД выбрать?
Существует огромное количество различных СУБД, и каждая из них соответствует определённому набору требований, которые разработчики предъявляют к своему приложению:
- Документоориентированные СУБД (к примеру, MongoDB): Как уже сказано выше, документоориентированные СУБД используются для хранения JSON-документов в “коллекциях” и осуществления запросов по нужным полям. Можно использовать эту базу данных для создания приложений, в которых не будет содержаться слишком большого количества связей. Хорошим примером такого приложения является движок для блог-платформы или хранения каталога продуктов.
- Графовые СУБД (например Neo4j): Графовая СУБД используется для хранения между субъектами, где узлы являются субъектами, а грани — связями. Например, если разработчики создают социальную сеть, и один пользователь подписывается на другого, то пользователи являются узлами, а их “подписка” — связью. Такие СУБД прекрасно справляются с образованием связей, даже если глубина таких связей более ста уровней. Этот инструмент столь эффективен, что может даже позволяет выявлять мошенничество в сфере электронной коммерции.
- Кэш (например Redis): Такие СУБД используются, когда требуется крайне быстрый доступ к данным. Если создается приложение для интернет-торговли, в котором есть подгружаемые на каждой страницы категории, то вместо обращения к базе данных при каждом чтении, что крайне затратно, можно хранить данные в кэше. Он позволяет быстро осуществлять операции чтения/записи. Дандала советует применять СУБД, использующие кэш, в качестве оболочки для обработки часто запрашиваемых данных, избавляющей от необходимости совершения частых запросов к самой базе.
- Поисковые СУБД (например ElasticSearch): В случае необходимости осуществления полнотекстового поиска по базе данных (например поиск продукции в ecommerce-приложении), то хорошей идее будет использование поисковой СУБД вроде ElasticSearch. Эта система способна искать по огромному массиву данных и обладает обширной функциональностью — например, СУБД умеет осуществлять поиск по именованным категориям.
- Строковые СУБД (например Cassandra): СУБД Cassandra используется для хранения последовательных данных, логов, или огромного объема информации, который может генерироваться автоматически — к примеру, каким-нибудь датчиками. Если разработчики собираются использовать СУБД для записи больших массивов данных и при этом планируется, что будет намного меньше обращений для чтения и данные не будут иметь связи и объединения, тогда Cassandra будет хорошим выбором, уверен Дандала.
Использование комбинации баз данных
Существуют и ситуации, в которых может понадобиться использование сразу нескольких различных СУБД.
Например, если в приложении есть функция поиска, то его можно реализовать с помощью ElasticSearch, а уже для хранения данных без связей лучше подойдет MongoDB. Если речь иет о проекте в сфере «интернета вещей», где огромное количество всевозможных устройств и датчиков генерируют гигантские объёмы данных, вполне разумно будет использовать Cassandra.
Принцип, при котором используются несколько СУБД для работы в одном приложении, называется “Polyglot Persistence”. В этой статье можно почитать о плюсах и минусах такого подхода.
Наш опыт
Наша биллинговая система «Гидра» использует для учета первичных данных и хранения финансовой информации реляционную СУБД. Она идеально подходит для этих целей. Но некоторые модули Гидры, например, RADIUS-сервер, работают под высокой нагрузкой и могут получать тысячи запросов в секунду с жесткими ограничениями на время обработки запроса. Кроме того, в БД нашего автономного RADIUS-сервера данные хранятся в виде набора AVP (attribute/value pair). В таком сценарии реляционная СУБД уже не выглядит лучшим решением, и тут на помощь приходит MongoDB с ее хранилищем документов произвольной структуры, быстрой выдачей ответа и горизонтальной масштабируемостью.
При эксплуатации более чем на 100 инсталляциях Гидры на протяжении последних 5 лет серьезных проблем с Mongo мы не обнаружили. Но пара нюансов все же есть. Во-первых, после внезапного отключения сервера БД хоть и восстанавливается благодаря журналу, но происходит это медленно. К счастью, необходимость в этом возникает нечасто. Во-вторых, даже при небольшом размере БД редко используемые данные сбрасываются на диск и когда запрос к ним все же приходит, их извлечение занимает много времени. В результате нарушаются ограничения на время выполнения запроса.
Все это относится к движку MMAPv1, который применяется в Mongo по умолчанию. С другими (WiredTiger и InMemory) мы пока не экспериментировали — проблемы не настолько серьезны.
Автор: Латера Софтвер