RAG без отдельной векторной БД: PostgreSQL + pgvector

Когда речь заходит о создании системы RAG (Retrieval-Augmented Generation), большинство разработчиков по инерции начинают смотреть в сторону специализированных векторных БД: Pinecone, Milvus или Weaviate. Маркетинг этих продуктов рисует картину, где без «нативного векторного хранилища» невозможно добиться производительности на миллионах документов.
Но давайте будем честными: для 90% бизнес-задач внедрение отдельной БД только для векторов — это неоправданное усложнение архитектуры. Вы добавляете в стек еще одну точку отказа, еще одну систему бэкапов, еще один механизм синхронизации данных и еще один счет в облачном биллинге.
В этой статье я разберу, почему связки PostgreSQL + pgvector более чем достаточно для реализации серьезного RAG-пайплайна и как это настроить, чтобы система не «легла» при первом же росте нагрузки.
Проблема «зоопарка» в ML-инфраструктуре
Типичный стек начинающего RAG-разработчика выглядит так:
-
- PostgreSQL для метаданных и пользователей.
-
- Pinecone/Milvus для векторных эмбеддингов.
-
- Redis для кэширования.
-
- S3 для хранения исходных документов.
Главная проблема здесь — консистентность. Представьте, что пользователь удаляет документ. Вам нужно синхронно удалить запись из реляционной базы и соответствующий вектор из векторной БД. Если один из запросов упадет, вы получите «фантомные» ответы от LLM, которые ссылаются на несуществующие данные.
Использование pgvector превращает эту распределенную систему в монолит в лучшем смысле этого слова. Ваши векторы лежат в той же транзакционной базе, что и бизнес-логика.
Что такое pgvector и как он работает «под капотом»
pgvector — это расширение для PostgreSQL, которое добавляет поддержку типа данных vector. По сути, это массив чисел с плавающей точкой, который позволяет выполнять операции вычисления расстояния между векторами прямо внутри SQL-запроса.
Вместо того чтобы выгружать данные из одной базы в другую, вы просто добавляете колонку embedding vector(1536) (для OpenAI) или vector(768) (для HuggingFace моделей) в существующую таблицу.
Основные механизмы поиска:
- L2 distance (Евклидово расстояние): Полезно, когда важна абсолютная разница в значениях.
- Inner Product (Скалярное произведение): Используется, если векторы нормализованы.
- Cosine Distance (Косинусное сходство): Стандарт индустрии для NLP, где важно направление вектора, а не его длина.
Архитектура RAG на базе PostgreSQL
Чтобы реализовать RAG без отдельной векторной БД, мы объединяем классический поиск по ключевым словам (Full Text Search) и семантический поиск (Vector Search). Это называется гибридным поиском, и именно здесь Postgres раскрывается на полную.
Пошаговый алгоритм реализации:
- Chunking и эмбеддинги:
Текст разбивается на части (чанки). Каждый чанк превращается в вектор с помощью модели (например,text-embedding-3-small). - Хранение:
Создается таблица, где в одной строке хранятся:id,document_id,content(текст чанка) иembedding(вектор). - Поиск (Retrieval):
При поступлении вопроса от пользователя он переводится в вектор. Затем выполняется SQL-запрос, который находит $N$ ближайших соседей. - Генерация (Generation):
Найденные текстовые фрагменты подаются в LLM вместе с вопросом в качестве контекста.
Оптимизация производительности: Индексы HNSW и IVFFlat
Многие говорят, что Postgres медленный на больших объемах. Это заблуждение, если вы понимаете, как работают индексы. По умолчанию поиск по векторам — это «полный перебор» (Exact Nearest Neighbor), что работает за $O(n)$. На 10 тысячах строк это незаметно, на миллионе — катастрофа.
Для ускорения используются два типа индексов:
1. IVFFlat (Inverted File Flat)
Разбивает пространство векторов на кластеры. Поиск идет только по ближайшим кластерам.
-
- Плюс: Быстрое создание индекса.
-
- Минус: Требует предварительного обучения (нужно иметь данные перед созданием индекса), точность может падать при изменении распределения данных.
2. HNSW (Hierarchical Navigable Small World)
Это «золотой стандарт» современного векторного поиска. Он строит многослойный граф, по которому алгоритм «прыгает» к ближайшему соседу.
-
- Плюс: Высочайшая точность и скорость поиска.
-
- Минус: Потребляет значительно больше оперативной памяти (RAM) и медленнее строится.
Совет из практики: Если у вас больше 100к документов и есть лишняя память — всегда выбирайте HNSW. Это даст вам отклик в миллисекундах.
Гибридный поиск: почему это киллер-фича
Чистый векторный поиск иногда «галлюцинирует» в плане точности. Например, если вы ищете конкретный серийный номер товара «SN-12345», векторный поиск может вернуть «похожие» товары, но не конкретный номер.
В PostgreSQL вы можете объединить tsvector (полнотекстовый поиск) и pgvector в одном запросе:
sql
SELECT content
FROM documents
WHERE (content @@ to_tsquery(‘serial_number’))
ORDER BY embedding <=> ‘[0.12, -0.05, …]’
LIMIT 5;
Такой подход позволяет сначала отфильтровать данные по жестким критериям (пользователь, дата, категория, ключевое слово), а затем ранжировать результат по семантическому сходству. В специализированных векторных БД такая фильтрация часто реализована через «пре-фильтры», которые могут работать неэффективно.
Когда всё-таки стоит уйти с PostgreSQL?
Было бы нечестно сказать, что Postgres идеален для всего. Есть сценарии, когда специализированные БД (типа Milvus) будут лучше:
- Экстремальный масштаб: Если у вас сотни миллионов или миллиарды векторов.
- Специфические требования к сжатию: Когда нужны методы квантования (Product Quantization) для экономии RAM.
- Распределенный поиск «из коробки»: Если вам нужно шардирование векторов по десяти серверам с автоматической балансировкой.
Но для большинства корпоративных приложений (внутренние базы знаний, поддержка клиентов, анализ документов компании) PostgreSQL с pgvector закрывает все потребности.
Итог и рекомендации по внедрению
Переход на pgvector упрощает DevOps-процессы и делает систему более надежной. Вместо того чтобы управлять двумя разными базами данных, вы управляете одной.
Мой чек-лист для старта:
- Установите расширение
pgvector(в большинстве облачных провайдеров, таких как AWS RDS или Azure, оно уже доступно). - Выберите модель эмбеддингов, исходя из размера окна контекста и стоимости.
- Используйте индекс HNSW для продакшена.
- Обязательно внедрите гибридный поиск (TSVector + Vector), чтобы избежать промахов при поиске точных совпадений.
- Мониторьте потребление RAM — HNSW держит граф в памяти, и при нехватке ресурсов база начнет свопиться, что убьет производительность.
RAG — это не про выбор «самой крутой» БД, а про качество данных и точность извлечения контекста. PostgreSQL дает вам стабильность и гибкость, которой не хватает многим «хайповым» векторным хранилищам.

