В DailyWatch наша панель «похожие видео» начиналась со скромного запроса к SQLite. Он объединял три таблицы, подсчитывал пересекающиеся теги и возвращал ранжированный список. Для небольшого каталога этого было достаточно. Кулинарное видео с тегами «italian» и «pasta» выводило другие ролики с такими же тегами, и пользователи кликали по ним. Результаты казались релевантными, так как метаданные были чистыми, а библиотека — небольшой.
Затем каталог вырос, и ожидания аудитории изменились. Людям не просто нужны были видео с идентичными тегами. Они хотели тот ролик, который сорок процентов зрителей смотрели сразу после текущего. Им нужен был нишевый канал, который постоянно всплывал в тех же ночных сессиях просмотра, даже если в его описании не было ни слова о начальном видео, а теги были скудными. Это поведенческие паттерны, а не совпадения по метаданным. SQLite не мог выразить их, не превращаясь в нечитаемое нагромождение self-join и рекурсивных обобщенных табличных выражений (CTE). Каждый новый сигнал, который мы пытались смоделировать — будь то совместный просмотр или смежность сессий — увеличивал задержку и когнитивную нагрузку. У нас была задача на графы, зажатая в реляционные рамки.
Я перенес слой рекомендаций на Apache AGE.
Apache AGE — это расширение PostgreSQL, которое добавляет графовые запросы openCypher в базу данных, которую вы уже используете. Это не отдельный сервер. Это не sidecar. Он работает внутри Postgres, а это значит, что мы могли построить сеть совместных просмотров, не разворачивая выделенный кластер Neo4j и не изучая совершенно новый регламент эксплуатации. Для небольшой команды без инженера по надежности баз данных это различие имело огромное значение.
Почему расширение лучше новой базы данных
Добавление графовой базы данных в ваш стек легко нарисовать на доске, но дорого поддерживать в продакшене. Вам понадобятся новые дашборды мониторинга, новые процедуры резервного копирования, новые пулы соединений и новая логика отказоустойчивости. AGE позволяет обойти всё это, так как работает внутри вашего существующего экземпляра Postgres.
Есть четыре практические причины, почему это сработало для нас.
- Никакой новой инфраструктуры. Поскольку AGE является расширением, ваш текущий график
pg_dump, существующие реплики и стандартные проверки состояния (health checks) Postgres продолжают работать. Вам не нужно убеждать команду эксплуатации присматривать за еще одним хранилищем данных. - Смешанные нагрузки в одном запросе. AGE позволяет писать Cypher внутри SQL. Вы можете выполнить обход графа для поиска подходящих видео, а затем объединить (join) полученный набор результатов с вашей реляционной таблицей
usersдля соблюдения региональных ограничений на контент или с реляционной таблицейsponsorships, чтобы понизить приоритет определенных каналов. Один запрос (round-trip). Два языка запросов, работающих сообща. - Портативность. Cypher — это открытый, хорошо документированный язык запросов к графам. Если DailyWatch перерастет AGE и позже потребуется миграция на Neo4j или Memgraph, логика запросов перенесется с минимальными переработками. Вы не привязаны к проприетарному диалекту.
- Совместимость. Поскольку данные в конечном итоге хранятся в PostgreSQL, ваши существующие инструменты на PHP или Python не меняются. Вы подключаетесь
