Введение
Весь цикл был посвящён реляционным БД — в заключительных статьях блока расширим перспективу: разберём, когда реляционная модель действительно не лучший выбор, и какие альтернативные модели данных (документ-ориентированные, ключ-значение, графовые) решают определённые задачи естественнее.
Концепция
Документ-ориентированные БД (MongoDB и аналогичные) хранят данные как самодостаточные, не обязательно строго структурированные документы (часто в формате, похожем на JSON), что естественно подходит для данных с действительно изменчивой, не предсказуемой заранее структурой между разными записями, или там, где вся «логическая сущность» естественно представляется единым, вложенным документом без необходимости в JOIN между множеством отдельных таблиц. Хранилища ключ-значение (Redis и аналогичные) оптимизированы для крайне быстрого доступа по известному ключу, без сложной структуры запросов, что подходит для кеширования (статья, упомянутая в основном цикле) и сессионных данных. Графовые БД (Neo4j и аналогичные) оптимизированы для данных, где связи между сущностями (а не сами сущности) являются основным предметом интереса запросов — социальные сети, рекомендательные системы, анализ сложных, многоуровневых взаимосвязей, для которых даже рекурсивные CTE (статья 405) реляционных БД могут быть менее естественны и эффективны, чем нативные графовые операции.
Пример кода: NoSQL vs SQL
-- Сравнение представления одних и тех же данных: реляционная модель против документной
-- РЕЛЯЦИОННАЯ модель (нормализованная, статья 402) — несколько связанных таблиц
CREATE TABLE products (id SERIAL PRIMARY KEY, name VARCHAR(200));
CREATE TABLE product_reviews (id SERIAL PRIMARY KEY, product_id INTEGER REFERENCES products(id), rating INTEGER, comment TEXT);
CREATE TABLE product_images (id SERIAL PRIMARY KEY, product_id INTEGER REFERENCES products(id), url VARCHAR(500));
-- получение полной информации о товаре требует JOIN трёх таблиц
-- ДОКУМЕНТНАЯ модель (концептуально, синтаксис MongoDB) — всё в одном документе
{
"_id": "product_123",
"name": "Ноутбук",
"reviews": [
{"rating": 5, "comment": "Отлично!"},
{"rating": 4, "comment": "Хорошо, но дорого"}
],
"images": ["https://example.com/img1.jpg", "https://example.com/img2.jpg"]
}
-- получение полной информации о товаре — ОДНА операция чтения документа, без JOIN вовсе
-- Когда документная модель оправдана: каталог товаров с РАЗНЫМИ наборами атрибутов
-- для разных категорий (ноутбуки, книги, одежда — у каждой совершенно свой набор полей)
-- В реляционной модели это решалось бы через JSONB (статья 423) или EAV-паттерн (избегаемый антипаттерн),
-- тогда как в документной модели это естественная, нативная часть самой модели данных
-- Когда документная модель НЕ подходит: данные с сильными, множественными перекрёстными связями
-- между разными типами сущностей, требующими сложных, многотабличных JOIN-подобных запросов —
-- для таких случаев реляционная модель с её нативной поддержкой JOIN остаётся предпочтительнее
Пояснения к коду
Сравнение представления товара с отзывами и изображениями в реляционной (три отдельные таблицы, требующие JOIN) и документной (единый, самодостаточный документ) моделях наглядно показывает фундаментальное архитектурное различие — документная модель естественно подходит для случаев, где данные конкретной «сущности» (товара) логически образуют единое целое, читаемое и записываемое как единый блок, без частой необходимости запрашивать или изменять лишь отдельные, изолированные части этой структуры независимо от остальных. Явное противопоставление «когда документная модель оправдана»/»когда не подходит» подчёркивает основной практический урок статьи — выбор между SQL и NoSQL не является выбором «лучшей» технологии в абсолютном смысле, а зависит от конкретной природы данных и паттернов их использования в конкретном проекте.
Подводные камни
- Выбор документной/NoSQL БД исключительно из-за общей популярности или маркетингового восприятия «современности» этого подхода, без анализа, действительно ли природа данных конкретного проекта соответствует сильным сторонам документной модели — для данных с действительно сильными, множественными связями между разными типами сущностей (что типично для очень многих, если не большинства бизнес-приложений) реляционная модель с её нативной поддержкой JOIN часто остаётся объективно более подходящим, естественным выбором, и переход на NoSQL без такого реального соответствия часто приводит к необходимости эмулировать реляционные возможности (связи, JOIN-подобные операции) на уровне кода приложения, что обычно сложнее и менее эффективно, чем использование нативной поддержки этих возможностей в реляционной БД.
- Денормализация данных до уровня полного дублирования во множестве документов (типичная практика документных БД, поскольку JOIN между документами обычно либо невозможен, либо неэффективен) без понимания связанного с этим риска рассогласования при изменениях — аналогично подводным камням статьи 403 про денормализацию в реляционных БД, но в документной модели эта проблема часто проявляется значительно острее, поскольку сама модель архитектурно подталкивает к большему дублированию данных по своей природе, и обновление одного и того же фрагмента информации, продублированного в множестве разных документов, требует явного, аккуратного управления этим процессом синхронизации.
- Использование документной БД для данных, требующих строгой, немедленной согласованности при сложных, многосущностных транзакциях (статья 408) — традиционные документные БД исторически давали более слабые гарантии согласованности при операциях, затрагивающих несколько разных документов одновременно, по сравнению с полноценными ACID-транзакциями реляционных БД (хотя современные версии многих документных БД существенно улучшили поддержку транзакций), и для данных, для которых строгая транзакционная согласованность действительно критична (финансовые операции, статья 408), это стоит явно проверить и учесть при выборе технологии.
- Смешивание SQL и NoSQL БД в одном проекте без чёткого, продуманного разделения ответственности между ними (что само по себе разумная, распространённая практика — polyglot persistence, использование разных технологий для разных частей системы согласно их естественным сильным сторонам) — без явного, документированного понимания, какие данные хранятся где и почему, со временем становится трудно поддерживать целостную картину архитектуры данных всей системы, аналогично подводному камню статьи 411 про распределённую между разными местами бизнес-логику.