NoSQL без фанатизма: когда это работает, а когда усложняет
Рамка применимости NoSQL через три реальных измерения: согласованность, нагрузка и стоимость сопровождения.
NoSQL появился как реакция на реальные ограничения реляционных баз при определённых сценариях нагрузки. Это честная и понятная история. Но за несколько лет вокруг него сложилась другая история - что реляционные базы устарели, что "настоящие" проекты так не делают, что гибкость схемы - это всегда хорошо.
Я встречал команды, которые выбирали NoSQL не потому что им это было нужно, а потому что так казалось профессиональнее. Это дорого обходилось. Тот же паттерн работает и с Hadoop - выбор инструмента не под задачу обходится дорого, сколь бы современным этот инструмент ни был.
Что NoSQL действительно решает
Есть несколько сценариев, где NoSQL-подходы дают реальное преимущество:
- Высокая запись с горизонтальным масштабированием. Если нужно принимать миллионы событий в секунду от распределённых источников, реляционная база становится узким местом. Системы вроде Cassandra или HBase проектировались под этот сценарий.
- Гибкость структуры документа. Если каждый объект может иметь разный набор полей и схема меняется быстро - документная модель (MongoDB, CouchDB) удобнее ALTER TABLE.
- Графовые связи. Если задача - обходить связи между сущностями на много уровней в глубину, графовая база справляется с этим органичнее, чем JOIN-ы.
- Пары ключ-значение с низкой латентностью. Кеш, сессии, счётчики - Redis закрывает это лучше, чем любая реляционная СУБД.
Во всех этих случаях выбор обоснован конкретным техническим требованием, которое можно показать пальцем.
Что NoSQL не решает - и часто усложняет
Гибкость схемы легко превращается в источник проблем. Когда у документов нет жёсткой структуры, ответственность за целостность данных перекладывается в код приложения. Это означает: несколько версий схемы в одной коллекции, логика миграции в разных местах, трудночитаемые запросы.
Транзакции - отдельная история. Большинство NoSQL-систем на момент их появления не поддерживали многообъектные транзакции с гарантиями ACID. Для операционных систем - учёт, заказы, финансы - это не академический вопрос. Это вопрос корректности данных.
Агрегации и отчётность тоже труднее. SQL для аналитических запросов до сих пор остаётся самым выразительным инструментом. Попытка делать сложные агрегации в документной базе или базе ключ-значение обычно заканчивается либо map-reduce, либо переносом данных в реляционную систему.
Три вопроса перед выбором
Я использую три параметра как фильтр:
Согласованность. Допустимо ли, что разные клиенты в один момент времени видят разные версии данных? Для ленты событий - да. Для остатка на счёте - нет.
Нагрузка. Есть ли у вас реальные измерения, что реляционная база не справляется с нужным объёмом? Или это предположение о будущей нагрузке? Преждевременный выбор под гипотетическую нагрузку - один из самых частых источников лишней сложности.
Стоимость сопровождения. Есть ли в команде люди, которые понимают, как эта база ведёт себя при сбоях, как делать резервные копии, как мигрировать схему? Операционная зрелость имеет значение.
Реляционные базы не умерли
PostgreSQL сегодня умеет хранить JSON-документы, делать полнотекстовый поиск, работать с массивами и поддерживает репликацию. Это не значит, что он заменяет специализированные NoSQL-системы в крайних сценариях. Но это значит, что для большинства задач среднего бизнеса реляционная база с нормальной схемой - это обоснованный выбор, а не признак отсталости.
Короткий фильтр
Перед тем как выбрать NoSQL-решение, стоит ответить честно:
- Какое конкретное ограничение реляционной базы мы обходим?
- Есть ли у нас данные о нагрузке, или мы предполагаем?
- Кто будет сопровождать это решение через год?
- Что мы теряем в транзакционности и как это компенсируем?
Если на эти вопросы нет чётких ответов - скорее всего, реляционная база является разумным выбором. NoSQL - это инструмент под задачу, а не стиль мышления.