Будет ли MongoDB правильным выбором для вашего приложения? Выбор базы данных — важный этап разработки приложения. Неправильный выбор может негативно сказаться как на процессах разработки и сопровождения вашего продукта, так и привести к снижению производительности. В принципе, можно использовать любую базу данных, и она будет работать. Но одна база данных лучше работает с одним типом рабочей нагрузки, а другая с другим. Не стоит выбирать MongoDB только потому, что это круто и ее используют много компаний. Вы должны понимать насколько она соответствует вашей рабочей нагрузке и ожиданиям. Поэтому выбирайте правильный инструмент. В этой статье мы обсудим несколько возможностей MongoDB, которые стоит знать прежде чем вы решитесь выбрать и развернуть ее. Базовым компонентом MongoDB является документ, очень похожий на JSON. Технически это BSON, который содержит некоторые дополнительные данные (например, datetime), которые недопустимы в JSON. Мы можем рассматривать документ как запись в реляционной базе данных. Документы помещаются в коллекции, которые соответствует концепции таблиц в реляционной базе данных. JSON-документы очень популярны среди программистов и используются при разработке веб-сервисов, приложений и для обмена данными. Работать с базой данных со встроенной поддержкой таких данных может быть действительно эффективно. Разработчики часто выбирают MongoDB, потому что ее можно начать использовать без специальных знаний об администрировании и проектировании баз данных, а также без изучения сложного языка запросов. Язык запросов MongoDB также представлен в формате JSON документов. Разработчики могут легко создавать, сохранять, запрашивать и изменять JSON-документы. Здорово! Обычно это значительно ускоряет разработку. Вы знакомы с реляционными базами данных? Наверняка да, ведь реляционные базы данных используются и изучаются уже очень давно и в школе и университете. В настоящее время на рынке это наиболее широко используемый тип баз данных. Реляционная схема требует предопределенной и фиксированной структуры таблиц. Каждый раз, когда вы добавляете или изменяете столбец, вам необходимо выполнить DDL-запрос, и приложить дополнительные усилия, чтобы изменить код вашего приложения для работы с новой структурой. В случае значительных изменений, требующих изменения нескольких столбцов и/или создания новых таблиц, изменения в приложении могут быть весьма значительными. Отсутствие схемы в MongoDB означает, что ничего из этого не требуется. Вы просто добавляете документ в коллекцию и все. Например, у вас есть коллекция с данными пользователя. Если в какой-то момент вам нужно добавить новое поле "date_of_birth", вы просто начинаете работать с новыми JSON-документами с дополнительным полем. И все. Нет необходимости менять что-либо в схеме. Вы также можете вставлять в одну и ту же коллекцию совершенно разные JSON-документы, представляющие разные сущности. Технически это осуществимо, но все же так делать не рекомендуется. MongoDB также значительно сокращает цикл разработки приложения по нетехнической причине — устраняется необходимость координации миграции изменений схемы базы данных с DBA. Нет необходимости ждать, пока команда DBA еще раз все проверит и выпустит релиз в продакшн (с планами отката), что, как правило, потребует еще и некоторого простоя. Проектирование реляционной базы данных должно осуществляться с учетом того, чтобы SQL-запросы могли выполнять различные JOIN для нескольких таблиц по определенным колонкам. Также необходимо предусматривать внешние ключи (foreign key) для контроля целостности данных и автоматических изменений в связанных полях. Что насчет хранимых процедур? Хранимые процедуры могут быть полезны для встраивания в базу данных некоторой логики приложения для упрощения ряда задач или повышения безопасности. А триггеры? Триггеры нужны для автоматического инициирования изменений данных при определенных событиях, таких как добавление / изменение / удаление строк. Они помогают управлять согласованностью данных и, в некоторых случаях, упростить код приложения. Но они отсутствуют в MongoDB. Так что имейте это в виду. Примечание: честно говоря, есть агрегирование, которое может реализовать то же самое, что и LEFT JOIN, но это единственный случай. Соединение (JOIN) должно выполняться в коде вашего приложения. Если требуется выполнить JOIN двух коллекций, то сначала нужно прочитать первую, выбрать поле для JOIN и использовать его для запроса второй коллекции и т.д. Это кажется весьма дорогим с точки зрения разработки приложения и может привести к увеличению количества запросов. И это действительно так. Хорошая новость заключается в том, что в большинстве случаев вам не придется использовать JOIN. Помните, что MongoDB — это база данных без схемы, не требующая нормализации. Если вы правильно спроектируете коллекции, то сможете встраивать (embed) и дублировать данные в одной коллекции без необходимости создания дополнительных коллекций. Таким образом, вам не придется выполнять соединение, потому что все данные, которые вам нужны, уже будут в одной коллекции. Внешние ключи не поддерживаются. Но так как можно встраивать в одну коллекцию несколько документов, они вам просто не нужны. Хранимые процедуры могут быть легко реализованы в виде внешних скриптов, написанных на любом языке программирования. Триггеры также реализуются снаружи с помощью Change Stream API. Если у вас много коллекций, содержащих ссылки на поля, то в коде приложения вам придется реализовать много JOIN или выполнить множество проверок для обеспечения согласованности. Это все возможно, но потребует больших затрат на разработку. В этом случае MongoDB может оказаться неправильным выбором. MongoDB изначально разрабатывалась для работы в распределенных окружениях. Она была задумана как часть большого пазла. Для реализации репликации и шардирования сервер mongod может работать совместно с другими экземплярами mongod без использования каких-либо сторонних инструментов. Replica Set (набор реплик) — это группа процессов mongod, которые обслуживают один и тот же набор данных, обеспечивая избыточность и высокую доступность. С оговорками, касающимися потенциально устаревших данных, вы также бесплатно получаете масштабируемость чтения. Для продакшн-решения всегда следует применять такую конфигурацию. Sharding Cluster развертывается как группа из нескольких Replica Set с возможностью разделения и равномерного распределения данных по ним. В дополнение к избыточности, высокой доступности и масштабируемости чтения Sharding Cluster обеспечивает масштабируемость записи. Топология шардинга подходит для развертывания очень больших наборов данных. Количество шардов, которые вы можете добавить, теоретически не ограничено. Обе топологии можно изменить в любое время, добавив больше серверов и шардов. Что еще более важно, никаких изменений в приложении не требуется, поскольку каждая топология полностью прозрачна с точки зрения приложения. И, наконец, развертывание таких топологий очень просто. Вначале вам придется потратить некоторое время, чтобы понять несколько основных концепций, но затем, в течение нескольких часов, вы сможете развернуть даже очень большой кластер с шардированием. В случае нескольких серверов вместо того, чтобы делать все вручную, вы можете автоматизировать многие вещи с помощью плейбуков Ansible или других подобных инструментов. Дополнительные материалы: Deploy a MongoDB Replica Set with Transport Encryption (Part 1) MongoDB Sharding 101 Webinar В MongoDB можно создавать индексы для полей JSON-документа. Индексы используются так же, как и в реляционных базах данных для ускорения выполнения запросов и уменьшения использования ресурсов компьютера: памяти, времени процессора и операций ввода-вывода в секунду (IOPS). Для всех регулярно выполняемых запросов, операций изменения и удаления данных необходимо создавать необходимые индексы, которые помогут ускорить их выполнение. MongoDB обладает очень мощными возможностями индексирования. Есть TLL-индексы, GEO Spatial — индексы для пространственных данных, индексы для элементов массива, частичные (partial) и разреженные (sparse) индексы. Если вы хотите подробнее изучить доступные типы индексов, вы можете обратиться к следующим статьям: MongoDB Index Types and MongoDB explain() (part 1) Using Partial and Sparse Indexes in MongoDB Создавайте все необходимые индексы для ваших коллекций. Они очень помогут вам улучшить общую производительность вашей базы данных. MongoDB интенсивно использует память. Нужно много памяти. Это относится и ко многим другим базам данных. Память, в большинстве случаев, - самый важный ресурс. MongoDB использует оперативную память для кэширования наиболее часто и недавно используемых данных и индексов. Чем больше этот кэш, тем лучше будет общая производительность, потому что MongoDB сможет быстрее извлекать большой объем данных. Кроме того, изменения данных происходят в памяти. Запись на диск выполняется асинхронно: сначала в файл журнала (обычно в пределах 50 мс), а затем в обычные файлы данных (один раз в минуту). WiredTiger — наиболее популярный движок хранения данных, используемый в MongoDB. Раньше это был MMAPv1, но в последних версиях он больше не доступен. Движок хранения WiredTiger использует кэш памяти (WiredTiger Cache) для кэширования данных и индексов. Помимо WTCache, для доступа к диску MongoDB использует кэш файловой системы. Это еще одна важная оптимизация, для которой также может потребоваться значительный объем памяти. Кроме того, MongoDB использует память для управления клиентскими соединениями, выполнения сортировки в памяти, временных данных при выполнении пайплайнов агрегации и другого. Будьте готовы обеспечить MongoDB достаточным объемом памяти. Но сколько нужно памяти? Эмпирическим правилом является оценка размера "рабочего набора". "Рабочий набор" — это данные, которые чаще всего запрашиваются вашим приложением. Типичное приложение работает с ограниченным объемом данных. При обычной работе ему не нужны все данные. Например, в случае с временными рядами (time-series data), скорее всего, вам нужно будет получить только последние несколько часов или дней. Только в редких случаях вам понадобится читать более старые данные. В таком случае в вашем рабочем наборе может будут храниться данные только за несколько дней. Предположим, что ваш набор данных составляет 100 ГБ, и вы оценили ваш рабочий набор в 20%, тогда вам потребуется как минимум 20 ГБ для WTCache. Так как по умолчанию для WTCache используется 50% памяти (обычно мы рекомендуем не увеличивать ее значительно), то на сервере должно быть 40 ГБ памяти. Каждый случай индивидуален, и иногда бывает трудно правильно оценить размер рабочего набора. В любом случае, основная рекомендация заключается в том, что вы должны предоставить максимальное количество памяти, которое можете себе позволить. Это будет полезно для MongoDB. На самом деле таких ситуаций очень много. Я видел использование MongoDB в самых разных приложениях. Например, MongoDB подходит для следующих типов приложений: логирование событий; управление контентом; игры; платежные системы; аналитика в режиме реального времени; приложения Интернета вещей; кеширование; приложения, обрабатывающие временные ряды. И для многих других. В принципе, вы можете использовать MongoDB практически для всего, так как это база данных общего назначения. Главное — это то, как вы ее используете. Например, если вы планируете использовать MongoDB как реляционную базу данных с нормализованными данными, множеством коллекций и большим количеством JOIN, тогда MongoDB будет не лучшим выбором. Используйте реляционную базу данных. Правильный способ использования MongoDB - придерживаться лучших практик и моделировать коллекции с учетом ряда правил, таких как встраивание документов вместо создания нескольких коллекций с полями-ссылками. Percona разрабатывает собственную версию MongoDB с открытым исходным кодом: Percona Server for MongoDB (PSMDB). PSMDB - это прямая замена MongoDB Community со 100% совместимостью. PSMDB отличает то, что вы бесплатно получаете следующий enterprise-функционал: шифрование; журнал аудита; LDAP-аутентификация; LDAP-авторизация; редактирование журнала; kerberos-аутентификация; горячий бэкап; in-memory storage engine. Без PSMDB все эти расширенные возможности доступны только в подписке MongoDB Enterprise. Более подробную информацию о PSMDB можно найти по следующим ссылкам: Percona Server for MongoDB Feature Comparison Percona Server for MongoDB Помните, что вы можете связаться с Percona в любое время, чтобы узнать подробности или получить помощь. Давайте подытожим, на что обращать внимание, прежде чем выбирать MongoDB в качестве базы данных для приложения. Случаи, когда MongoDB будет хорошим выбором: Ваши приложения в основном работают с JSON-документами; Ваши данные непредсказуемы и бывают частые изменения схемы; Вам требуется высокая доступность и масштабируемость чтения; Вам нужно масштабировать данные очень большого размера; Требуется масштабирование из-за огромного количества операций записи. Условие, при котором MongoDB может быть хорошим выбором, но с некоторыми ограничениями или потенциально узкими местами: Вам необходимо реализовать хранимые процедуры и триггеры, которые есть в вашей реляционной базе данных. Условие, при котором MongoDB не будет хорошим выбором: У вас есть несколько коллекций с большим количеством ссылок для обеспечения целостности данных, и большинство запросов требуют JOIN. И напоследок запомните следующее: чем больше памяти на сервере, тем лучше; анализируйте ваши запросы и создавайте правильные индексы; постоянно мониторьте поведение базы данных; рассмотрите возможность внедрения PSMDB для получения базы данных enterprise-класса бесплатно; обращайтесь в Percona за консультациями. Посмотрите на Percona Server for MongoDB. Перевод материала выполнен в рамках курса "MongoDB". Если вам интересно узнать о курсе больше, приглашаем на день открытых дверей онлайн.   Переводчик, редактор