Руфат Нуриев обновлено

Neo4j на практике: когда граф лучше обычной БД

Сравнение графовой модели данных и сложных табличных JOIN-связей на экране ноутбука

Neo4j - графовая СУБД, в которой данные живут как узлы и связи, а не как строки в таблицах. Обычная реляционная БД (PostgreSQL, MySQL) отлично закрывает транзакции, отчёты и CRUD. Но когда ценность продукта в путях, цепочках и многошаговых связях, SQL с JOIN и рекурсивными CTE (именованными подзапросами, которые могут ссылаться сами на себя) быстро становится тяжёлым и хрупким. Ниже - практические признаки, когда Neo4j выигрывает у «обычной» БД, и когда граф ещё рано.

  • Граф - узлы (сущности) + рёбра (типизированные связи) + свойства
  • Сильная сторона Neo4j - обход связей на переменную глубину
  • Слабое место SQL - глубокие JOIN, «друзья друзей», цепочки fraud/доступов
  • Не замена - транзакционный CRUD, складской учёт, классическая аналитика
  • Правило - берите Neo4j, когда вопрос звучит как «через кого / через что / за N шагов»

Схема гибридной архитектуры: транзакции в SQL, связи в графе на прозрачной доске

Чем граф отличается от таблиц

В PostgreSQL вы моделируете связи через foreign keys и таблицы связей (user_roles, follows, order_items). Запрос с фиксированной глубиной ещё читаем. Запрос «найди все узлы в радиусе 3-5 hops с фильтрами по типу связи» уже превращается в рекурсивный CTE или несколько JOIN - и план выполнения растёт вместе с глубиной.

В Neo4j связь - полноценная сущность модели. Модель ближе к тому, как люди описывают домен:

  • (:Person)-[:WORKS_AT]->(:Company)
  • (:Account)-[:TRANSFERED_TO]->(:Account)
  • (:User)-[:HAS_ROLE]->(:Role)-[:ALLOWS]->(:Permission)

Запрос на языке Cypher описывает паттерн, а не «склейку таблиц». Это удобно, когда глубина пути заранее неизвестна или часто меняется.

Что это значит для владельца бизнеса

Графовая БД - не апгрейд обычной базы, а отдельный сервис в инфраструктуре со своими навыками, лицензией и эксплуатацией. Прежде чем утверждать такой проект, стоит спросить у команды: решает ли Neo4j конкретную бизнес-задачу (антифрод, рекомендации, права доступа) или добавляется «про запас», кто будет писать и поддерживать Cypher-запросы, и сколько стоит синхронизация с основной базой данных. Если ответ на первый вопрос расплывчатый, дешевле сначала проверить гипотезу на обычной БД - раздел «Когда обычная БД всё ещё лучше» ниже поможет понять, ваш ли это случай.

Когда Neo4j лучше обычной БД

Берите граф, если в ТЗ регулярно встречаются такие задачи:

  1. Переменный обход связей - «друзья друзей», цепочка поставок, путь до корневого владельца.
  2. Паттерн-матчинг по связям - найти подграфы вида «A связан с B через C при условии D».
  3. Рекомендации и похожие сущности по графу - не только по тексту, а по общим соседям и путям.
  4. Антифрод и риск - кольца, общие устройства, короткие пути между «чужими» счетами.
  5. Права и зависимости - кто к чему имеет доступ через роли, группы и наследование.
  6. Граф знаний - продукты, документы, люди, системы и явные отношения между ними.

Признаки, что SQL уже «болит»:

  • рекурсивные CTE на каждом релизе становятся длиннее;
  • команда боится менять схему связей;
  • задержка растёт именно на глубоких JOIN, а не на простых SELECT;
  • бизнес спрашивает «покажи цепочку», а не «дай строку по id».

Практический пример: путь и общие соседи

Допустим, нужно найти компании, связанные с человеком не более чем через два шага, и отфильтровать по типу связи.

MATCH path = (p:Person {id: $personId})-[:WORKS_AT|KNOWS*1..2]-(c:Company)
WHERE c.country = $country
RETURN DISTINCT c.name AS company, length(path) AS hops
ORDER BY hops, company
LIMIT 50;

Тот же смысл в SQL обычно требует рекурсии, аккуратной дедупликации и ограничений по глубине. В графе формулировка ближе к вопросу бизнеса.

Пример «общие соседи» для рекомендаций:

MATCH (u:User {id: $userId})-[:BOUGHT]->(:Product)<-[:BOUGHT]-(other:User)
WHERE u <> other
WITH other, count(*) AS shared
ORDER BY shared DESC
LIMIT 20
RETURN other.id, shared;

Когда обычная БД всё ещё лучше

Neo4j - не универсальная замена PostgreSQL.

Оставляйте реляционную БД (или начинайте с неё), если:

  • основной поток - CRUD, заказы, платежи, склад, биллинг;
  • связи фиксированной глубины (1-2 JOIN) и стабильны годами;
  • нужны тяжёлые агрегаты, окна, отчётность в стиле BI;
  • команда уже сильна в SQL, а графовых запросов единицы;
  • объём «сетевой» логики мал и закрывается одним CTE без боли;
  • бюджет и штат не рассчитаны на эксплуатацию второй БД.

Типичная ошибка: перенести весь продукт в Neo4j «потому что графы модные». Получите лишнюю операционку и слабое соответствие для транзакционного ядра.

Гибрид: PostgreSQL + Neo4j

На практике часто работает разделение:

Слой Где хранить Зачем
Заказы, пользователи, платежи PostgreSQL / MySQL Транзакции, целостность, отчёты
Связи, пути, роли, зависимости Neo4j Traversal и pattern match
Поиск по смыслу текста Векторное хранилище RAG / семантический поиск

Источник истины для денег и статусов - реляционная БД. Граф синхронизируют событиями - через outbox (таблицу исходящих событий), CDC или очередь - либо батчами. Так вы не дублируете биллинг в Neo4j и не пытаетесь строить fraud-граф на одних JOIN.

Как проверить гипотезу за 1-2 недели

  1. Выпишите 15-20 реальных вопросов пользователей/аналитиков.
  2. Отметьте, сколько из них - про пути, hops и «через кого».
  3. Если таких заметно больше трети (это ориентир, а не строгий порог), соберите пилот на Neo4j с урезанным подграфом.
  4. Сравните с SQL: читаемость запроса, задержка p95 (95-й процентиль задержки), сложность изменений схемы.
  5. Оцените стоимость синхронизации данных с основной БД.

Если пилот не даёт выигрыша по задержке/понятности - оставайтесь на PostgreSQL. Граф должен решать боль, а не украшать архитектуру.

Итог

Neo4j лучше обычной БД там, где продукт думает связями: цепочки, роли, зависимости, fraud, граф знаний, рекомендации по графу. Обычная БД лучше там, где ядро - транзакции, фиксированные JOIN и отчёты. Часто оптимален гибрид: SQL для фактов и денег, граф для структуры и путей.

Если нужно решить, стоит ли выносить связи в Neo4j, или спроектировать пилот под ваш домен - свяжитесь со мной.

Часто задаваемые вопросы

Чем Neo4j принципиально лучше PostgreSQL для связей?

Скоростью и ясностью обхода на переменную глубину. В графе рёбра индексируются как связи, а не собираются каждый раз через JOIN таблиц. Для 1-2 фиксированных JOIN PostgreSQL часто достаточно; для «N hops с фильтрами по типу связи» Neo4j обычно проще и стабильнее.

Можно ли заменить Neo4j рекурсивными CTE в PostgreSQL?

Иногда да, на старте. Если глубина мала, объём графа умеренный, а запросов мало - CTE работают. Когда растут глубина, ветвление и число pattern-запросов, CTE становятся сложными в поддержке и дорогими по плану выполнения.

Нужно ли переносить весь продукт в Neo4j?

Нет. Переносите слой, где связи - продуктовая ценность. Заказы, платежи, склад и классический CRUD оставляйте в реляционной БД. Иначе получите слабое соответствие и лишнюю сложность эксплуатации.

Cypher сложнее SQL?

Другая ментальная модель, не обязательно сложнее. Для путей и паттернов Cypher короче и читаемее. Для агрегатов, отчётности и оконных функций SQL привычнее. Команде нужен короткий онбординг и 5-10 эталонных запросов по домену.

С чего начать внедрение Neo4j в существующий проект?

С пилота на одном сценарии: например, граф доступов, fraud-кольца или карта зависимостей сервисов. Определите источник истины, способ синхронизации и 10 контрольных вопросов. Только после замера задержки и доли попаданий решайте о расширении на другие домены.

Сколько это стоит и нужна ли под это отдельная команда?

Это отдельная статья расходов, а не бесплатное дополнение к текущей БД. У Neo4j есть открытая community-версия для пилота и платные варианты (enterprise-лицензия, managed-облако) для продакшена со своим SLA и поддержкой - выбор зависит от масштаба и требований к отказоустойчивости. В любом случае нужен инженер, который умеет проектировать графовую модель и писать Cypher-запросы: либо обучаете текущую команду, либо нанимаете/привлекаете на аутсорс. Плюс расходы на синхронизацию с основной БД (см. раздел про гибрид). Закладывайте это в оценку до пилота, а не после решения о переходе в прод.

Термины в статье

паттерн — reusable solution pattern for a common design problem — повторно используемый приём для типовой задачи проектирования

BI — Business Intelligence — бизнес-аналитика

RAG — Retrieval-Augmented Generation — генерация с дополненным поиском

CDC — Change Data Capture — захват изменений данных

онбординг — user onboarding — первые шаги пользователя в продукте

SLA — Service Level Agreement — соглашение об уровне обслуживания

прод — production — боевая среда с реальными пользователями (production)

Контакты