Ваш RAG-пайплайн ляжет под нагрузкой в первый же день продакшена, и виновата будет не медленная LLM, а неправильно выбранная векторная база. Выбор векторной базы на свои данные: pgvector, Qdrant или FAISS — что выдержит вашу нагрузку, решается не на созвонах с вендорами, а холодной математикой и жесткими ограничениями по памяти. Иллюзий быть не должно. Каждое решение имеет свой архитектурный потолок, пробивая который вы получаете деградацию p95 latency с десятков миллисекунд до неприемлемых секунд таймаутов.
Всего существует три класса решений для векторного поиска. Первый — это расширение для вашей текущей реляционной базы, и в девяноста процентах случаев это pgvector поверх PostgreSQL. Второй класс — специализированные векторные движки, спроектированные специально для эмбеддингов, такие как Qdrant, Milvus или Weaviate. Третий — низкоуровневые алгоритмические библиотеки вроде FAISS. Выбор между ними сводится к трейд-оффам между планируемым объемом векторов, жесткими требованиями к QPS, необходимостью сложной фильтрации по метаданным и частотой обновления индекса в закрытом on-prem контуре, где нельзя спастись, просто арендовав сервера побольше.
В основе любого из этих решений лежат алгоритмы приближенного поиска ближайших соседей (ANN). Архитектурный выбор на этом уровне сводится к двум основным подходам: HNSW и IVF. Хотите максимальный recall и готовы безжалостно сжигать оперативную память серверов? Ваш выбор HNSW. Это графовый индекс, который работает феноменально быстро и обеспечивает точность поиска, близкую к абсолютному максимуму. Плата за это — гигантское потребление RAM. Индекс HNSW всегда должен полностью лежать в памяти для обеспечения предсказуемой задержки. Считаем в лоб. Миллион векторов размерности 1536 во float32 весит около шести гигабайт чистыми. Графовые связи добавят еще от тридцати до пятидесяти процентов объема. Итого около девяти гигабайт оперативной памяти на каждый миллион записей. В on-prem инфраструктуре это быстро становится критическим ограничением. Не хватает памяти? Вы падаете в своп диска, и ваша latency пробивает дно.
Альтернатива — инвертированный индекс IVF. Он потребляет кратно меньше памяти и быстрее строится. Но при поиске он выдает худший recall и заставляет тонко настраивать количество кластеров для обхода. Вам придется регулярно обучать центроиды кластеров, перестраивая индекс каждый раз, когда распределение данных смещается. IVF заставит вас балансировать параметр nprobe — сколько кластеров обойти во время запроса. Ставите мало — теряете релевантные куски контекста для LLM. Ставите много — приближаетесь по задержкам к полномасштабному линейному сканированию. Трейд-офф между recall, latency и потреблением памяти невозможно обойти архитектурным трюком. Его можно только принять.
Индексы HNSW и предел прочности pgvector
Инженеры выбирают pgvector за простоту. У вас уже развернут кластер PostgreSQL, вы накатываете расширение, создаете колонку типа vector и начинаете писать запросы на привычном SQL. Это идеальное решение для старта. Вектора лежат в одной транзакции с бизнес-логикой, ACID работает из коробки, бэкапы снимаются проверенными годами инструментами. Нет необходимости тащить в стек еще одну сложную распределенную систему и объяснять DevOps-команде, как ее масштабировать.
До какого момента pgvector будет держать удар? Зависит от железа, но золотой стандарт для этого расширения — от одного до пяти миллионов векторов. На этом объеме при правильном тюнинге параметров разделяемой памяти PostgreSQL p95 latency держится в районе двадцати-пятидесяти миллисекунд. Это отличный показатель для большинства внутренних корпоративных RAG-приложений.
Где он ломается? На пересечении роста объема и сложной фильтрации. Вы перешагиваете порог в десять миллионов записей. Ваш HNSW индекс раздувается. PostgreSQL, пытаясь удержать этот монолитный индекс в shared buffers, начинает агрессивно вытеснять оттуда другие критичные данные. Вся ваша реляционная база начинает деградировать. Но настоящая катастрофа наступает при гибридном поиске. Представьте, что вам нужно найти топ похожих документов по вектору, но строго среди тех, которые созданы конкретным отделом за последние три дня.
Базе приходится делать выбор: либо сначала искать соседей по вектору, а потом отбрасывать результаты, не подходящие по дате и отделу, либо сначала фильтровать строки, а потом сканировать вектора. Это называется post-filtering и pre-filtering. В pgvector механизм гибридного поиска все еще уступает специализированным решениям. Запрос может отработать за десятки миллисекунд, а может зависнуть на секунды, если планировщик ошибся с оценкой кардинальности выборки и решил сканировать миллионы строк перед векторным сравнением. В этот момент мнимая простота эксплуатации перестает окупать деградацию производительности.
Когда пора переходить на Qdrant или голую FAISS
Выделенная векторная база становится неизбежной, когда счет векторов идет на десятки миллионов, а нагрузка вырастает до сотен запросов в секунду. Специализированные движки вроде Qdrant проектировались для векторного поиска с первого дня. Они решают ровно те проблемы, о которые спотыкается Postgres.
Главное оружие Qdrant — грамотная работа со сложной фильтрацией по метаданным. Индекс изначально умеет отсекать ветви графа, не подходящие под условия, еще на этапе навигации по узлам HNSW. Никаких внезапных тормозов при узких фильтрах. Кроме того, Qdrant умеет использовать memory-mapped файлы (mmap), сбрасывая часть графа на диск без катастрофического падения latency. Это критически важно в on-prem развертываниях, где ресурсы серверов строго квотированы. Да, вы платите за это усложнением инфраструктуры. Это плюс одна база данных. Ее нужно разворачивать, настраивать репликацию, шардирование и мониторинг. Но если ваш продукт — это высоконагруженный RAG по десяткам миллионов эмбеддингов, другого пути нет. Иначе вы просто сожжете сервера в попытках затюнить PostgreSQL.
Что насчет FAISS? Это не база данных. Это голый алгоритмический движок. В нем нет сетевого API по умолчанию, нет ролевой модели, нет транзакций и нет нормального способа удалять одиночные вектора из построенного индекса без полной перестройки. Если бизнес-требования подразумевают постоянное потоковое обновление базы документов, FAISS превратится в кошмар поддержки. Нужно ли использовать ее для RAG в стандартном корпоративном портале? Нет.
Зачем она нужна? Для инференса на edge-устройствах и хардкорного процессинга в изолированных контурах. Edge-вычисления не прощают раздутого стека. Вы не потащите тяжеловесный докер-контейнер с базой на локальный промышленный сервер с ограниченным теплопакетом. Когда у вас есть замороженный датасет на сотни миллионов векторов, и вам нужно искать по нему с максимальной плотностью вычислений. Вы пересчитываете индекс раз в сутки, собираете бинарный артефакт и подгружаете его в оперативную память напрямую из вашего кода. В FAISS вы можете использовать Product Quantization, чтобы ужать объем индекса в десятки раз ценой контролируемой потери точности. Это дает нулевые потери на сетевой оверхед и позволяет выжимать десятки тысяч QPS на одном физическом сервере.
Иллюзия универсального инструмента убивает проекты. Разработка высоконагруженных on-prem систем требует циничного расчета. Начинайте с pgvector, чтобы проверить продуктовую гипотезу и наладить RAG-пайплайн малыми силами. Когда метрики начнут ползти вниз на десятке миллионов записей, а пользователи пожалуются на таймауты при фильтрации по тегам, стисните зубы и переносите поиск в Qdrant. А FAISS оставьте для тех сценариев, где ваша архитектура требует хирургического вмешательства в память и процессорное время, а не просто комфортного хранения текстов для языковой модели.