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 лучше обычной БД
Берите граф, если в ТЗ регулярно встречаются такие задачи:
- Переменный обход связей - «друзья друзей», цепочка поставок, путь до корневого владельца.
- Паттерн-матчинг по связям - найти подграфы вида «A связан с B через C при условии D».
- Рекомендации и похожие сущности по графу - не только по тексту, а по общим соседям и путям.
- Антифрод и риск - кольца, общие устройства, короткие пути между «чужими» счетами.
- Права и зависимости - кто к чему имеет доступ через роли, группы и наследование.
- 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 недели
- Выпишите 15-20 реальных вопросов пользователей/аналитиков.
- Отметьте, сколько из них - про пути, hops и «через кого».
- Если таких больше ~30-40%, соберите пилот на Neo4j с урезанным подграфом.
- Сравните с SQL: читаемость запроса, latency p95, сложность изменений схемы.
- Оцените стоимость синхронизации данных с основной БД.
Если пилот не даёт выигрыша по 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 решайте о расширении на другие домены.