№ 063
04 июня 2026
4 мин чтения

Рекурсия на сервере: как Интеграм обходит деревья и графы одним запросом

Большинство бизнес-данных — это связи: подразделение внутри подразделения, «похожие» записи одна за другой. Чтобы пройти такую структуру вглубь, обычно идут в код приложения — десятки запросов. Интеграм обходит дерево или граф и сразу ранжирует результат за один серверный вызов.

Рекурсия на сервере: как Интеграм обходит деревья и графы одним запросом

Большинство бизнес-данных — это не плоские таблицы, а связи: подразделение внутри подразделения, категория внутри категории, «похожие» записи, тянущиеся одна за другой. Чтобы пройти такую структуру вглубь — от корня до листьев или от записи к её соседям — нужна рекурсия. Обычно за ней идут в код приложения: выгрузил один уровень, спросил следующий, и так десятки раз. Каждый шаг — отдельное обращение к серверу.

Интеграм умеет иначе: обойти всю структуру вглубь и сразу её отсортировать — за один серверный вызов.

Откуда берётся рекурсия

Движок отчётов Интеграма опирается на нативный механизм MySQL WITH RECURSIVE — стандартный способ писать рекурсивные запросы прямо в СУБД. Поверх него работает композиция: запись вида [имя_отчёта] подставляет один сохранённый отчёт внутрь другого как подзапрос. Вы собираете сложный обход из простых кирпичиков-отчётов, а сервер разворачивает его в один SQL-запрос. Никакого отдельного «движка обхода» и никакой выгрузки промежуточных уровней в приложение.

Кейс 1. Деревья: оргструктура, каталоги, меню

Подчинённые таблицы Интеграма — это и есть деревья: запись ссылается на родителя (c.id = ref.up). Рекурсивный отчёт спускается от любого узла до самых листьев одним запросом: все подразделения внутри департамента, все подкатегории товара, всё дерево пунктов меню. Тот же механизм Интеграм использует и у себя — чтобы собрать ролевое меню по вложенной структуре.

Что это даёт на практике: «показать все заказы по всем дочерним филиалам», «свернуть и развернуть категорию со всем вложенным» — без ручных джойнов на каждый уровень и без потолка «только два-три уровня вглубь».

Кейс 2. Графы: память по смыслу

Связи бывают не древовидными, а сетевыми — «похоже на это». На этом построен наш эксперимент IME (Integram Memory Engine): дать приложению память по смыслу прямо в рабочей базе, без отдельной векторной СУБД.

Идея в трёх шагах. Текст превращается в вектор — набор чисел, у похожих по смыслу текстов наборы похожи. Близость векторов (косинус) считает обычный отчёт Интеграма. А чтобы не сравнивать запрос с миллионами записей, у каждой записи хранятся ссылки на несколько ближайших соседей — получается граф «знакомств», и поиск идёт по нему прыжками: спроси соседа, кто ещё ближе к теме.

Вот здесь рекурсия и решает. Раньше обход графа шёл из клиента: около 82 обращений к серверу, примерно 33 секунды на один поиск. Рекурсивный отчёт собирает окрестность графа (поиск вширь до заданного бюджета) и ранжирует её косинусом в одном запросе: зерно → рекурсивное расширение → косинус → top-k.

Способ обходаОбращений к серверуВремя
обход из клиента~82~33 с
один рекурсивный запрос1~0.3 с

Это около 100× по времени. На живой базе ideav.ru/mem выигрыш индексного поиска над полным перебором растёт с объёмом: 2.1× при 60 записях → 12.7× при 5000, при точности recall@1 95–100%.

Честно про границы

Рекурсия снимает боль «обхода вглубь», но не превращает Интеграм в векторную СУБД:

  • каждый шаг обхода — это сетевое обращение; для миллисекундных задержек на больших корпусах выделенный ANN-индекс (FAISS, Qdrant, pgvector) всё равно быстрее по константе;
  • нативного векторного индекса нет — близость считается сканом по тексту, и на больших объёмах он медленнее;
  • инкрементальное сопровождение рёбер графа при каждой вставке мы пока не доказали — в прототипе граф строился пакетно.

Прямые аналоги, которые умеют и рекурсию, и вектора, — это Postgres с pgvector и Neo4j. На больших объёмах они мощнее, но это отдельная инфраструктура. Ценность подхода Интеграма не в самом примитиве WITH RECURSIVE, а в композиции: вектора, рёбра, рекурсия и косинус живут в одной таблице рядом с бизнес-данными — без новой базы и без бюджета сверху.

Что забрать с собой

Рекурсивные отчёты плюс композиция [имя] превращают связи в обходимые структуры: деревья — от корня до листа, графы — от записи к её соседям, и всё это одним серверным вызовом. Для иерархий это убирает ручные джойны по уровням; для «похоже на это» — открывает память по смыслу прямо внутри приложения.

Подробности и цифры — в репозитории эксперимента ideav/ime: на пальцах, прототип и результаты, сравнение с векторными СУБД.

← Все выпуски
Выпуск № 063