← К списку статей

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

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

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

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

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

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

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

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

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

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

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

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

  • рекурсивные CTE на каждом релизе становятся длиннее;
  • команда боится менять схему связей;
  • latency растёт именно на deep 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 «потому что графы модные». Получите лишнюю операционку и слабый fit для транзакционного ядра.

Гибрид: PostgreSQL + Neo4j

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

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

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

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

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

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

Итог

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

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

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

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

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

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

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

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

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

Cypher сложнее SQL?

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

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

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

Контакты