awesome-everything EN
↑ Обратно к восхождению

Базы данных

Реляционная модель vs документные, wide-column, граф и key-value

Суть Точные условия победы каждой модели данных, почему Postgres покрывает больше, чем подразумевает ярлык «реляционный», различия pgsql vs MySQL, важные для проектирования схемы, и разбор решения для мультитенантной схемы.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 16 min

Стартап принял MongoDB, потому что «реляционные схемы жёсткие». Три года спустя ad-hoc джойны невозможны, целостность данных обеспечивается приложением (непоследовательно), и команда переезжает на Postgres. Жёсткость, которую они хотели избежать, была дисциплиной, которая их бы спасла.

Пространство компромиссов

Реляционная модель — одна из нескольких моделей данных. Опытные инженеры знают, где побеждает каждая альтернатива и где «просто использовать Postgres» превосходит «выбрать специализированный инструмент».

Документные хранилища (MongoDB, Firestore, DynamoDB). Побеждают, когда документы доступны как единицы и никогда не джойнятся. Один документ содержит все данные одной сущности (продукт с вложенными вариантами, медиа и атрибутами). Кросс-документная целостность не нужна. Паттерн запросов — «получить этот документ по ключу» или «фильтр по верхнеуровневым полям». Проигрывают при ad-hoc запросах, операциях эквивалентных JOIN или ссылочной целостности между документами.

Wide-column хранилища (Cassandra, ScyllaDB). Побеждают при очень высокой пропускной способности записи (~100k+ записей/секунду) с заранее определёнными паттернами запросов, не меняющимися после проектирования схемы. Первичный ключ Cassandra включает partition key (как данные распределены) и clustering key (как данные сортируются внутри партиции) — запросы, совпадающие с partition key, быстрые; любой другой запрос — полный скан. Проигрывают при эволюции паттернов запросов или необходимости агрегации.

Граф-базы данных (Neo4j, Dgraph, Amazon Neptune). Побеждают, когда обход графа — доминирующий запрос: «найти всех друзей друзей в 3 переходах», «обнаружить циклические платёжные пути», «найти кратчайший путь в knowledge graph». Проигрывают во всём остальном. Рекурсивные CTE в SQL могут заменить многие граф-запросы на малом масштабе; на большом масштабе или при обходе как основной нагрузке нативная граф-БД дешевле.

Key-value хранилища (Redis, DynamoDB в режиме KV). Побеждают для чистых точечных поисков по известному ключу — хранение сессий, кеши, флаги фич, кратковременные счётчики. Проигрывают при любых диапазонных запросах, агрегации или обходе связей.

МодельПобеждает когдаПроигрывает когдаПримеры
РеляционнаяПовторяющаяся схема, ad-hoc запросы, кросс-типовая целостностьЧистый документный доступ, only-known-key нагрузки при экстремальном масштабеPostgres, MySQL
ДокументнаяГетерогенная схема per-row, документный unit-доступAd-hoc запросы, целостность между документамиMongoDB, Firestore
Wide-columnОчень высокая пропускная запись, фиксированные паттерны запросовЭволюция запросов, агрегацияCassandra, ScyllaDB
ГрафГлубокий обход как основной запросВсё остальноеNeo4j, Amazon Neptune
Key-valueЧистый точечный поиск по известному ключуДиапазонные запросы, агрегация, обход связейRedis, DynamoDB (KV mode)

Postgres — не только реляционная БД

Самоописание Postgres — «самая продвинутая реляционная СУБД с открытым исходным кодом в мире». На практике экосистема расширений покрывает большинство нагрузок, которые можно было бы адресовать специализированному хранилищу:

  • JSONB + GIN-индексы — документоподобные запросы без документного хранилища.
  • pg_vector — поиск векторного сходства (ближайших соседей для AI-эмбеддингов), заменяет специализированные векторные базы данных для большинства нагрузок.
  • PostGIS — полноценный геопространственный движок (пространственные индексы, гео-операторы), заменяет специализированные geo-хранилища.
  • TimescaleDB — партиционирование и сжатие временных рядов, заменяет InfluxDB для многих нагрузок.
  • pgcrypto — шифрование, хэширование, UUID из криптографического источника.
  • Recursive CTE — ограниченный обход графа без граф-базы данных.

Вопрос «нужно ли мне специализированное хранилище?» становится: «превышает ли моя нагрузка то, что может сделать Postgres + нужное расширение?» Для большинства команд до ~10 ТБ и без требований экстремальной пропускной записи ответ — нет.

Postgres vs MySQL: дефолты проектирования схемы, имеющие значение

Обе реляционные; обе реализуют большую часть SQL:2011. Различия, важные при проектировании схемы:

Поведение NULL в UNIQUE constraints. Стандарт SQL (и Postgres) допускает несколько NULL в UNIQUE-колонке (NULL не равен ничему, включая другой NULL). InnoDB MySQL также допускает несколько NULL. Но MySQL исторически (до 8.0) имел другое поведение NULL в некоторых операциях. Используйте Postgres UNIQUE NULLS NOT DISTINCT (SQL:2023), если хотите предотвратить дублирующиеся NULL.

Неявное приведение типов. MySQL более снисходителен — молча преобразует '42' в 42, усекает строки, превышающие длину VARCHAR, вместо ошибки. Postgres строгий — неправильные типы дают явную ошибку. Поведение Postgres выявляет несоответствия схемы раньше.

Дефолтный движок хранения. MySQL по умолчанию использует InnoDB; старый тулинг иногда использует MyISAM (нет транзакций, нет поддержки FK). В 2026 году все продакшн-использования MySQL должны быть на InnoDB. У Postgres один движок хранения без ловушки.

Экосистема. Postgres: PostGIS, TimescaleDB, pg_vector, pgcrypto, citus, pgroll. Экосистема MySQL: Vitess (горизонтальное масштабирование), PlanetScale (MySQL-as-a-service), Aurora MySQL (AWS). Выбирайте MySQL, если глубоко в экосистеме горизонтального масштабирования MySQL (Vitess, PlanetScale, Aurora MySQL); иначе Postgres для нового проекта.

Мультитенантное проектирование схемы: разбор решения

Самое сложное решение схемы для B2B SaaS — изоляция тенантов. Три паттерна:

Schema-per-tenant. Каждый workspace получает собственную Postgres-схему. Полная DDL-изоляция. Миграции выполняются per-schema (n схем × 1 миграция = n операций). Работает до ~1000 тенантов; выше этого накладные расходы на соединения и сложность миграций растут линейно. Переключение тенанта чистое (SET search_path).

Database-per-tenant. Максимальная изоляция. Запретительно сложно выше ~100 тенантов. Подходит для enterprise SaaS с требованиями изоляции по контракту.

Изоляция на уровне строк (колонка workspace_id + RLS). Одна схема, все тенанты в тех же таблицах. Каждая тенантная таблица имеет workspace_id BIGINT NOT NULL. Политики Postgres Row-Level Security (RLS) фильтруют строки на основе session-level GUC:

ALTER TABLE projects ENABLE ROW LEVEL SECURITY;

CREATE POLICY projects_tenant_isolation ON projects
  USING (workspace_id = current_setting('app.current_workspace_id')::BIGINT);

Соединение приложения устанавливает SET app.current_workspace_id = X после аутентификации. RLS гарантирует, что каждый запрос на этом соединении видит только строки workspace X. Пропущенный WHERE в коде приложения поймает RLS.

Эшелонированная защита: RLS + CI-линтер, требующий workspace_id в каждом WHERE. Линтер ловит баги до продакшна; RLS — страховочная сеть.

Почему это работает

Зачем добавлять CI-линтер, если RLS уже применяет изоляцию? RLS — гарантия, а не сообщение об ошибке. Запрос, нарушающий RLS, молча возвращает ноль строк (или выдаёт ошибку, если настроен как RESTRICTIVE). Разработчик видит «нет результатов» и предполагает, что данных нет. CI-линтер проваливает сборку, когда запрос обращается к тенантной таблице без workspace_id, давая actionable ошибку до того, как запрос попадёт в продакшн.

Выбери лучший вариант

Новая социальная фича нуждается в 'найти всех друзей друзей в 2 переходах' для движка рекомендаций. В таблице users 10M строк и 50M follow-связей. Выберите подход к запросу.

Викторина

Команда из 200 B2B клиентов рассматривает изоляцию schema-per-tenant. При каком масштабе этот паттерн становится операционно дорогим и почему?

Викторина

Postgres Row-Level Security включена, политика ограничивает строки `workspace_id = current_setting('app.current_workspace_id')`. Запрос приложения случайно опускает WHERE workspace_id. Что происходит?

Вспомните перед уходом
  1. 01
    Сформулируйте, почему реляционная модель побеждает документные, wide-column, граф и key-value альтернативы для большинства B2B SaaS нагрузок, и дайте одно конкретное условие победы для каждой альтернативы.
  2. 02
    Каковы три паттерна мультитенантной изоляции для Postgres и когда применяется каждый?
  3. 03
    Назовите два различия в дефолтах проектирования схемы между Postgres и MySQL.
Итог

Реляционная модель побеждает для нагрузок с повторяющейся структурой, ad-hoc запросами и критически важной целостностью — большинство B2B SaaS, fintech, операционных инструментов. Документные хранилища побеждают для документного unit-доступа без кросс-документной целостности. Wide-column побеждает при экстремальной пропускной записи с фиксированными запросами. Граф побеждает, когда обход — основной запрос. Key-value побеждает для чистых точечных поисков. Postgres с расширениями (JSONB, pg_vector, PostGIS, TimescaleDB) покрывает большинство специализированных потребностей в одном движке. Для мультитенантного SaaS: изоляция на уровне строк с RLS — по умолчанию; schema-per-tenant для контрактной изоляции до ~1000 тенантов; database-per-tenant для enterprise контрактов. Postgres vs MySQL: Postgres строже (ошибки типов, NULL-семантика) и имеет богатую экосистему расширений; выбирайте MySQL только для специфических потребностей экосистемы или шардинга.

Связанные уроки
встречается в140
Продолжить восхождение ↑Реляционная модель: тест с множественным выбором
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources4
expand
  1. 01
  2. 02
  3. 03
  4. 04

Trademarks belong to their respective owners. Editorial reference only.