Содержание
Векторная база данных — это не «ещё одно место для документов», а слой индекса и хранения для поиска ближайших по смыслу фрагментов: векторы, идентификаторы, фильтры и служебные атрибуты. Отдельный продукт нужен, когда приближенный поиск ближайших соседей, жёсткая задержка, частые обновления, изоляция арендаторов и гибрид лексики со смыслом перестают укладываться в обычный PostgreSQL с расширением pgvector. Пока корпус умеренный, транзакции уже живут в PostgreSQL, а целевые процентили выдерживаются на реальных фильтрах, отдельная база часто преждевременна.
Ниже — промышленный разбор слоя хранения, а не всей цепочки RAG. Концептуальный минимум — в главе о векторных базах. Как устроена вся конвейерная цепочка извлечения — в промышленной инженерии RAG.
Ключевые выводы
Векторная база — производный индекс, а не система истины. Оригинал документа, версия, права доступа и срок действия живут в каноническом хранилище. База векторов хранит представление для поиска и должна уметь полностью перестроиться из манифеста.
Приближенный поиск ближайших соседей — это явный компромисс полноты, задержки и памяти. HNSW, инвертированный файл (IVF), квантование и дисковые графы вроде DiskANN решают одну задачу разными ценами. Число из чужого сравнительного теста без ваших фильтров и модели векторов ничего не доказывает.
Фильтр по правам и арендатору — часть запроса к индексу, а не пост-обработка. Если система сначала достаёт «похожие» фрагменты, а потом отбрасывает запрещённые, запрещённый текст уже мог попасть в трассу, кэш и контекст модели.
PostgreSQL с расширением pgvector — разумная первая промышленная точка. Он выигрывает, когда векторы живут рядом с транзакционными данными, объём ещё умещается в предсказуемый бюджет памяти и команда не хочет второй операционный контур. Он проигрывает, когда появляются миллионы векторов с жёстким 95-м процентилем, плотные фильтры, квантование и дисковый индекс как норма, а не эксперимент.
Смена модели векторных представлений — миграция данных, а не смена конфигурации. Размерность, метрика и версия модели — часть схемы. Смешивать векторы разных моделей в одном индексе нельзя.
Удаление — такой же контракт, как вставка. Мягкая пометка, отложенное сжатие и «забытый» идентификатор в графе — типичные причины, почему отозванный документ продолжает всплывать в ответах.
Что такое векторная база vs реляционная vs поисковый движок
Реляционная база отвечает на вопрос «какие строки удовлетворяют предикату». Она сильна там, где есть схема, соединения, транзакции и точные предикаты: номер договора, статус, дата, внешний ключ. Поисковый движок отвечает на вопрос «какие документы лучше соответствуют тексту запроса». Он силён в лексике: морфология, статистика термов, BM25, подсветка, фасеты. Векторная база отвечает на третий вопрос: какие объекты ближе всего к данному вектору в выбранной метрике, обычно с дополнительными предикатами по атрибутам.
Это разные физические операции. Поиск ближайших соседей в сотнях или тысячах измерений не сводится к дереву по одному столбцу и не сводится к инвертированному списку термов. Поэтому появляются отдельные структуры: граф связей, список групп (инвертированный файл), квантованные коды, дисковые страницы графа.
На практике три слоя часто сосуществуют, а не заменяют друг друга.
flowchart LR
app[Приложение] --> q[Запрос]
q --> v[Вектор запроса]
q --> f[Фильтры прав и атрибутов]
v --> idx[Векторный индекс]
f --> idx
q --> lex[Лексический индекс]
f --> lex
idx --> ids[Идентификаторы кандидатов]
lex --> ids
ids --> canon[Канонические фрагменты]
Документ как юридический объект остаётся в системе-источнике или в объектном хранилище. Реляционная база держит факты и права. Поисковый движок держит текст для точных идентификаторов и редких терминов. Векторный индекс держит числовые представления и ссылки. Если свернуть всё в одну «магическую» базу, вы либо потеряете транзакционные гарантии, либо заплатите за поиск по смыслу там, где достаточно BM25, либо будете хранить тяжёлые оригиналы в движке, который для этого не предназначен.
Отдельная векторная база оправдана как сервис индекса, когда:
- число векторов и частота запросов требуют специализированного приближенного поиска;
- фильтры по арендатору и полезной нагрузке должны исполняться внутри поиска, а не после него;
- нужна независимая масштабируемость чтения и записи относительно транзакционного ядра;
- команда готова сопровождать второй контур: резервные копии, наблюдение, переиндексацию, квоты памяти.
Она не оправдана, если задача — «положить PDF в базу и спросить LLM». В такой постановке ломается не выбор движка, а граница ответственности: кто владеет оригиналом, кто считает векторы, кто удаляет устаревшее.
Корпоративный контур, в котором векторный индекс — один сервис среди подготовки, лексики, повторного ранжирования и генерации, описан в архитектуре промышленного RAG. Здесь мы остаёмся на границе «как устроен индекс и что он обещает».
Векторы и метрики
Векторное представление (часто говорят «эмбеддинг») — это числовой образ фрагмента или запроса. Модель отображает текст в пространство фиксированной размерности. Близость в этом пространстве коррелирует со смысловой близостью на том распределении, на котором модель училась — и не гарантирует полезность для вашего корпуса. Подробный разбор, зачем вообще нужны векторные представления и где у них границы, — в материале «Почему эмбеддинги изменили корпоративный поиск». Здесь важны только следствия для хранения.
Индекс обязан знать три вещи и не смешивать их молча:
- Размерность. Вектор длины 384 нельзя положить в индекс, собранный под 1024, «дописав нули».
- Метрику. Косинус, скалярное произведение и евклидово расстояние (
L2) — разные порядки. Модель, которую учили под косинус, нельзя без проверки гонять в индексе сL2. - Версию модели. Даже две модели с одинаковой размерностью и «косинусом» дают несовместимые пространства.
Нормированные векторы делают косинус и скалярное произведение практически взаимозаменяемыми; ненормированные — нет. Если поставщик говорит «используйте скалярное произведение», проверьте, нормирует ли он выходы сам. Ошибка метрики выглядит как «поиск внезапно стал глупым» после смены клиента, а не как падение сервиса.
Не храните в индексе «голый» вектор без идентификатора фрагмента, идентификатора документа, версии модели, времени действия и ключа доступа. Эти поля — не украшение схемы, а то, что позволяет фильтровать, удалять и перестраивать. Сам текст фрагмента можно держать в индексе для удобства отладки, но каноном он быть не должен: иначе обновление парсера превращается в расхождение двух истин.
Приближенный поиск ближайших соседей: HNSW, IVF, квантование, DiskANN — полнота vs задержка vs память
Точный поиск ближайших соседей на миллионах векторов — это последовательный перебор или структура, которая в высоких размерностях деградирует к перебору. Поэтому промышленные индексы делают приближенный поиск ближайших соседей: они обещают высокую полноту (долю истинных соседей среди найденных), а не математическую полноту всех соседей. Полнота, задержка и память связаны. Улучшение одной оси почти всегда двигает две другие.
Граф HNSW
HNSW (Hierarchical Navigable Small World) строит многослойный граф: на верхних слоях — длинные «трассы», на нижнем — плотные связи ближайших точек. Поиск спускается с грубого слоя к точному. Параметры, которые команда реально крутит:
M— число связей у узла. БольшеM— выше полнота и расход памяти, медленнее вставка.efConstruction— ширина поиска при построении. Выше — качественнее граф, дольше индекс.efSearch(или аналоги) — ширина поиска при запросе. Это ваш основной рычаг «полнота против задержки» без перестройки.
Сильные стороны: высокая полнота при хорошем подборе, стабильная задержка на «простых» запросах без жёстких фильтров, предсказуемое поведение на средних объёмах. Слабые: граф любит оперативную память; вставки в большой граф дороже, чем в кластерный индекс; жёсткие фильтры ломают связность — поиск идёт по рёбрам сходства, а не по предикату «этот арендатор».
Память грубо складывается из самих векторов плюс списка соседей. Для миллионов точек с float32 и немаленьким M счёт идёт на десятки гигабайт ещё до полезной нагрузки. Именно поэтому появляются квантование и дисковые варианты, а не «ещё один сервер побольше».
Инвертированный файл (IVF) и родственники
IVF (иногда IVFFlat) сначала разбивает пространство на группы — обычно методом k-средних. В индексе хранятся центры групп и списки векторов внутри. Запрос смотрит не все группы, а nprobe ближайших к вектору запроса. Параметры:
nlist— число групп. Слишком мало — длинные списки и слабая отсечка. Слишком много — шумная кластеризация и риск промахнуться мимо нужной группы.nprobe— сколько групп смотреть в запросе. Это прямой рычаг полноты и задержки.
Сильные стороны: меньше накладных расходов графа, проще понять «мы смотрим 8 из 1024 групп», легче сочетать с квантованием кодов внутри группы. Слабые: полнота чувствительна к качеству кластеризации; после большого потока вставок распределение групп устаревает; при перекосе данных часть групп раздувается.
IVF часто выбирают, когда векторов много, память ограничена, а команда готова калибровать nprobe на своём наборе, а не копировать чужие числа.
Квантование
Квантование сжимает вектор: 8-битное скалярное, произведение подпространств (PQ), двоичные коды. Цель — уместить индекс в память или ускорить сравнение за счёт работы с кодами, а не с float32. Цена — потеря различения близких точек. На практике квантование почти всегда комбинируют с переранжированием короткого списка полными векторами: сначала грубый проход по кодам, затем уточнение.
Ошибка эксплуатации — включить максимальное сжатие, потому что «в таблице написано ×16 экономии», и удивляться падению полноты на пограничных запросах. Сжимайте то, что измеряете. Храните полный вектор отдельно, если собираетесь переранжировать; иначе экономия памяти съедает качество на последней миле.
Дисковые графы: DiskANN и соседи
Когда векторы и граф не помещаются в оперативную память, появляются индексы, рассчитанные на твердотельный накопитель: DiskANN (граф Vamana и страничная укладка), дисковые режимы у Milvus и Qdrant, различные схемы «горячий граф в памяти, векторы на диске». Идея одна: уменьшить случайные чтения, держать в памяти навигационный каркас, ходить на диск за векторами и соседями пакетами.
Это не «бесплатная бесконечная ёмкость». Задержка начинает зависеть от очереди диска, фрагментации и кэша страниц. Пиковая полнота при холодном кэше и при прогретом кэше — разные числа. Нагрузочный тест обязан включать прогрев и долю уникальных запросов, иначе вы измерите кэш операционной системы, а не индекс.
Как выбирать структуру
Не начинайте с названия алгоритма. Зафиксируйте:
- объём и рост числа векторов на год;
- допустимую оперативную память на реплику;
- целевые 95-й и 99-й процентили на запросе с боевыми фильтрами;
- долю обновлений (вставка, замена, удаление) относительно чтения;
- нужен ли жёсткий фильтр «один арендатор из десятков тысяч».
Грубые ориентиры, не законы: до сотен тысяч векторов точный или простой HNSW часто достаточен; миллионы в памяти — HNSW плюс квантование или IVF; десятки миллионов и ограничение памяти — дисковый граф или внешний сервис, который это умеет. Любой ориентир бьётся о ваши фильтры: индекс без предиката и индекс с tenant_id = X — разные системы.
Чужие сравнительные тесты полезны как карта возможностей, вредны как выбор победителя. Смотрите, совпадают ли размерность, метрика, распределение, доля фильтрованных запросов и режим записи. Если не совпадают — это чужая задача.
Фильтры, мультитенантность, гибрид на стороне хранилища
Семантическая близость без предиката — лабораторный режим. В продакшене почти каждый запрос несёт ограничения: арендатор, роль, язык, тип документа, срок действия, «только утверждённое», «не черновик». Вопрос не в том, есть ли фильтры, а в том, на каком этапе они применяются.
Предфильтр, постфильтр и поиск с учётом предиката
Постфильтр: взять k ближайших, выбросить неподходящие. На редком предикате вы получите пустую выдачу при том, что подходящие векторы в индексе есть. На секретном предикате вы ещё и протащите запрещённые фрагменты через слой извлечения.
Предфильтр: сначала сузить множество идентификаторов, затем искать среди них. На узком множестве это может быть точный перебор. На широком — отдельный индекс по атрибутам плюс векторный проход.
Поиск с учётом предиката: движок использует индекс по полезной нагрузке (значениям атрибутов) во время обхода графа или групп, чтобы не ходить в заведомо запрещённые узлы и не терять полноту. Именно это продают Qdrant (индексы полезной нагрузки), Weaviate (фильтры в запросе), поздние версии pgvector (итеративные сканы), плагины k-ближайших в OpenSearch и Elasticsearch. Качество реализации разное: у графа связность построена по сходству, а не по арендатору, поэтому «фильтр на лету» — отдельная инженерная задача, а не галочка в документации.
Правило безопасности: запрещённый фрагмент не должен попадать в кандидатский список приложения. Проверка прав — детерминированный предикат доверенной стороны, а не инструкция модели.
Изоляция арендаторов
Три рабочих модели:
- Коллекция (индекс) на арендатора. Жёсткая изоляция, простые фильтры, дорогой операционный хвост: тысячи маленьких индексов, неравномерная нагрузка, сложнее квоты. Оправдано при сильных требованиях к изоляции данных и редком числе крупных арендаторов.
- Общий индекс плюс обязательный предикат
tenant_id. Дешевле сопровождать, опаснее ошибиться в запросе. Нужны индексы по атрибуту, запрет запросов без предиката на уровне API, аудит. - Сегментация (физическое разбиение) по арендатору или группе. Компромисс: меньше коллекций, чем арендаторов, лучше локальность, сложнее ребалансировка.
«Шумный сосед» — не метафора: горячий арендатор забивает очередь построения графа и кэш страниц. Квоты записи, отдельные пулы запросов и наблюдаемость по ключу арендатора нужны с первого промышленного клиента, а не после инцидента.
Удаление по требованию субъекта данных должно доходить до вектора, полезной нагрузки и всех реплик, а не только до канонического файла. Иначе индекс становится теневой копией персональных сведений.
Гибрид на стороне хранилища
Гибридный поиск — совместное использование лексического и векторного сигналов. Часть продуктов умеет это внутри одного запроса: разреженные векторы и плотные в Qdrant, гибридный запрос в Weaviate, tsvector рядом с pgvector в PostgreSQL, лексика плюс k-ближайшие в OpenSearch/Elasticsearch. Слияние рангов, в том числе reciprocal-rank fusion, подробно разобрано в материале о гибридном поиске. Здесь важна граница слоя хранения.
Если движок умеет вернуть два упорядоченных списка и стабильные идентификаторы — гибрид можно собрать рядом, в приложении. Если вы уже платите за второй контур векторной базы, имеет смысл спросить, не дешевле ли отдать первый проход ей: меньше сетевых круглых поездок, единые фильтры, одна трасса. Если лексика уже сильна в существующем поисковом кластере, векторный сервис может остаться узким специалистом по плотным векторам, а слияние произойдёт выше.
Не подменяйте гибрид «просто увеличить k у векторов». Идентификаторы, артикулы, коды ошибок и точные цитаты лексика находит надёжнее. Векторный канал закрывает перефразирование и синонимию подразделений. Разбиение документа на фрагменты, от которого зависит оба канала, — отдельная дисциплина; практические постановки есть в экспериментах с разбиением.
Карта продуктов: pgvector, Qdrant, Weaviate, Pinecone, Milvus, Chroma, k-ближайшие в OpenSearch/Elasticsearch
Карта ниже — не рейтинг и не замена нагрузочного теста. Она отвечает на вопрос «какую операционную модель вы покупаете». Клиентские библиотеки на Python, упаковка и сюрпризы пути из ноутбука в сервис разобраны отдельно: пять Python-библиотек векторных баз.
| Продукт | Чем является | Индекс и поиск | Где уместен | Типичная цена выбора |
|---|---|---|---|---|
pgvector |
расширение PostgreSQL |
HNSW, IVFFlat, квантованные типы в свежих версиях, SQL-фильтры |
векторы рядом с транзакциями; умеренный объём; одна команда сопровождения | конкуренция с OLTP за ресурсы; сложнее специализированные фильтры и дисковые графы |
Qdrant |
специализированная база (Rust), своя инфраструктура или облако | HNSW, квантование, индексы полезной нагрузки, разреженные векторы |
фильтры и гибрид как норма; самохостинг без смены API | отдельный контур; нужно проектировать коллекции и атрибуты |
Weaviate |
специализированная база, модули, гибридный запрос | вектор + лексика в одном запросе, схема классов | когда хотите схему и гибрид «из коробки» | миграции схемы; операционная сложность модулей |
Pinecone |
управляемый сервис | собственные индексы, серверная модель ёмкости | мало своей эксплуатации, быстрый выход | сеть обязательна; привязка к поставщику; стоимость на объёме |
Milvus |
облачно-ориентированная система, часто с отдельными координаторами и хранилищем | HNSW, IVF, DiskANN, GPU-сценарии |
очень большие коллекции, раздельные роли узлов | тяжёлее эксплуатация; имеет смысл при реальном масштабе |
Chroma |
встроенная / лёгкая база для разработки | удобный локальный цикл | прототип, тесты, личный контур | не стоит делать неявным ядром продакшена без плана миграции |
OpenSearch / Elasticsearch |
поисковый движок с k-ближайшими | лексика + вектор в знакомом кластере | вектор как дополнение к уже живущему поиску | векторный контур конкурирует с текстовым за кучу и память; своя кривая версий |
Как читать таблицу. Если у вас уже есть зрелый кластер OpenSearch и запросы в основном лексические, добавлять узкий векторный канал туда часто дешевле, чем поднимать Milvus. Если транзакционная правда уже в PostgreSQL, а поиск по смыслу — функция одного продукта, pgvector снижает число систем. Если фильтры по полезной нагрузке и гибрид с разреженными векторами — ежедневная нагрузка, Qdrant или Weaviate ближе к задаче, чем «ещё один столбец в OLTP». Если команда из трёх человек не хочет сопровождать индекс, управляемый сервис снимает ночные дежурства и добавляет счёт и зависимость от сети.
Отдельно про сравнительные тесты «кто быстрее». Они чувствительны к тому, считаете ли вы построение индекса, прогрев, фильтрацию, квантование, сериализацию клиента и сборку полезной нагрузки. Продукт, выигравший чистый поиск без предиката, может проиграть на запросе «этот арендатор, этот язык, документы младше года». Измеряйте свой запрос.
Ещё один скрытый критерий — модель обновлений. Одни системы хорошо живут с пакетной перестройкой раз в сутки, другие обещают относительно свежие вставки в граф. Если регламент меняется днём, а индекс догоняет ночью, это уже продуктовое решение, а не настройка efSearch.
Эксплуатация: версия модели векторов, переиндексация, удаление, стоимость
Продакшен слоя индекса начинается после того, как «вставка работает на стенде». Четыре сюжета ломают системы чаще, чем выбор HNSW против IVF.
Версия модели как часть схемы
Каждая точка должна нести model_id (имя, ревизия, размерность, метрика). Поиск обязан указывать ту же версию, которой посчитан запрос. Две модели в одной коллекции без разделения — тихая порча пространства: полнота падает, а мониторинг «сервис жив» зелёный.
Смена модели — это новый индекс или новая коллекция, двойная запись на время миграции, сравнение полноты на контрольном наборе и переключение чтения. Нельзя «доэмбеддить» недостающие документы старой моделью в новый индекс. Нельзя считать, что облачный поставщик сохранит пространство при смене имени модели за вас: это ваш контракт.
Практический приём: идентификатор фрагмента неизменен, а векторные проекции версий живут рядом (vec_v3, vec_v4) или в параллельных коллекциях. Приложение выбирает проекцию явно. Откат — смена указателя, а не ночная пересборка «назад в неизвестность».
Переиндексация
Полная перестройка нужна при смене модели, метрики, алгоритма индекса, схемы атрибутов, правил разбиения (последнее — уже граница с конвейером RAG). Частичная — при порче сегмента, после массового удаления, когда квантование или группы IVF перекосились.
Делайте переиндексацию сине-зелёной: старый индекс обслуживает чтение, новый строится из канона, проверка на контрольном наборе, переключение, наблюдаемый период, только потом удаление старого. Строительство «на месте» с несовместимой схемой оставляет окно, в котором часть запросов видит смесь миров.
Идемпотентность загрузчика важнее скорости: один и тот же документ той же версии не должен плодить дубликаты с разными внутренними id. Дубликаты крадут слоты в top_k и создают ложное ощущение полноты.
Удаление и право быть забытым
Три уровня, которые путают:
- Скрыть из выдачи — фильтр «не показывать». Быстро, но вектор и текст остаются.
- Логическое удаление — пометка, исключение из поиска, отложенное физическое вычищение. Граф
HNSWможет долго держать «надгробия»; полнота и задержка деградируют, пока не пройдёт сжатие. - Физическое удаление — запись исчезла с диска и из реплик. Нужно для персональных данных и грубых ошибок загрузки.
Контракт удаления включает: каноническое хранилище, все проекции векторов, кэши, резервные копии (с политикой, а не с магией «сразу везде»), журналы, которые сами по себе могут содержать фрагмент. Если юридический срок «стереть за 30 дней», индекс с отложенным сжатием через 45 дней — нарушение процесса, а не мелочь движка.
Проверяйте удаление так же, как вставку: контрольный запрос, который должен стать пустым.
Стоимость
Счёт векторного слоя редко равен строке в облачном прайсе. Складывайте:
- оперативную память реплик (часто главная статья для
HNSWбез квантования); - диск и число операций ввода-вывода в секунду, если индекс дисковый;
- CPU на построение и на квантование;
- пересчёт векторов при смене модели (часто дороже хранения);
- сеть до управляемого сервиса и единицы тарификации там;
- человеческое время на второй контур наблюдения и резервного копирования.
Дешёвый управляемый индекс при дорогом пересчёте векторов — ложная экономия. Дорогой самохостинг при редких запросах и малом объёме — тоже. Считайте стоимость успешного поиска (запрос, который вернул нужный фрагмент в пределах задержки), а не стоимость гигабайта в вакууме.
Наблюдаемость минимума: задержка по процентилям с разбивкой «с фильтром / без», полнота на контрольном наборе после каждой смены индекса, очередь вставок, доля удалений, размер графа или групп, ошибки несовпадения размерности, запросы без tenant_id, если такой предикат обязателен.
Когда хватает PostgreSQL и когда нужна отдельная база
PostgreSQL с расширением pgvector закрывает удивительно большой класс промышленных задач: внутренний помощник на десятках или сотнях тысяч фрагментов, векторы рядом с сущностями домена, транзакционная вставка «строка бизнеса + вектор», знакомый резервный контур, SQL-предикаты, которые юристы и аудиторы понимают без нового языка запросов. Свежие версии добавили HNSW, итеративные сканы при фильтрах и более плотные типы хранения. Это уже не «игрушечное расширение 2023 года».
Отдельная база нужна, когда хотя бы несколько сигналов складываются, а не когда маркетинговый слайд обещает «миллиарды векторов».
| Сигнал | Скорее pgvector |
Скорее отдельная база |
|---|---|---|
| Объём | сотни тысяч — низкие миллионы, предсказуемый рост | многие миллионы / миллиарды, неравномерный рост |
| Нагрузка | поиск не спорит с OLTP за те же ядра и память |
отдельный профиль I/O, нужны выделенные узлы |
| Фильтры | SQL-предикаты и умеренная селективность | плотные атрибуты, разреженные векторы, гибрид как основной путь |
| Задержка | целевые процентили держатся на боевых запросах | 95/99 не держатся после настройки ef/nprobe и железа |
| Эксплуатация | одна команда БД, один контур копий | готовность ко второму контуру или к управляемому сервису |
| Изоляция | крупные арендаторы, схема в SQL | тысячи арендаторов, квоты, сегментация индекса |
| Обновления | пакеты, допустима минутная свежесть | частые замены, жёсткий контур удаления, квантование/диск как норма |
Решение принимайте нагрузочным тестом на копии боевого распределения: те же фильтры, та же доля пустых предикатов, тот же размер полезной нагрузки, та же доля вставок. Синтетический «миллион случайных векторов без фильтра» хвалит граф и обманывает планировщика.
Миграция с pgvector не обязана быть драмой. Часто оставляют PostgreSQL системой истины и прав, а векторный сервис забирает только проекцию для поиска. Двойная запись на время сверки полноты дешевле, чем «переезд всех документов в новую базу», которой документы не нужны.
Обратная ошибка — начать с Pinecone или Milvus на пилоте из трёх тысяч фрагментов, потому что так было в туториале. Вы покупаете сеть, счёт и чужой операционный ритм до того, как поняли, какой у вас предикат и какая полнота вообще требуется.
Типичные ошибки
Хранить оригиналы только в векторной базе. Индекс начинает жить своей жизнью: парсер обновили, а «истина» в полезной нагрузке устарела. Канон — отдельно, проекция — отдельно.
Искать без предиката доступа, фильтровать в приложении. Это дыра и источник пустой выдачи. Предикат должен быть частью запроса к индексу и частью контракта API.
Смешать модели векторных представлений. Тихий провал качества. Версия модели — обязательное поле и обязательный параметр поиска.
Копировать параметры M, efSearch, nlist из статьи. Чужие числа сняты на чужой размерности, чужой метрике и без ваших фильтров. Калибруйте на контрольном наборе.
Включить максимальное квантование без переранжирования полными векторами. Экономия памяти на бумаге, потеря различения на пограничных запросах.
Считать Chroma в контейнере «базой продакшена». Удобный цикл разработки не заменяет резервное копирование, изоляцию арендаторов и план роста. Путь из ноутбука ломается на упаковке клиента чаще, чем на алгоритме соседей — об этом как раз обзор Python-библиотек.
Не иметь пути удаления. Отозванный регламент, ошибочно загруженный договор, требование субъекта данных — без физического контура индекс помнит лишнее.
Оценивать движок запросами без фильтров. Вы выберете победителя лабораторного режима и проиграете в первый же день с tenant_id.
Путать задержку индекса с задержкой RAG. Сеть до модели, переранжирование и сборка контекста часто дороже поиска. Оптимизируйте по трассе, а не по одному микробенчмарку соседей.
Расти копированием коллекций вручную. Без манифеста версий через полгода никто не знает, какой индекс обслуживает какой продукт.
Частые вопросы
Нужна ли отдельная векторная база для любого RAG?
Нет. Для умеренного корпуса и уже живого PostgreSQL расширение pgvector часто закрывает слой поиска по смыслу. Отдельный продукт появляется, когда задержка с фильтрами, объём, изоляция арендаторов или гибрид перестают укладываться в этот контур.
Чем HNSW отличается от IVF на практике?
HNSW — граф в памяти с высокой полнотой и дорогой вставкой; IVF — поиск по нескольким группам пространства, дешевле по накладным расходам, сильнее зависит от nprobe и качества кластеризации. Выбор калибруют на своём наборе, а не по названию.
Можно ли хранить сами документы в векторной базе?
Можно как кэш фрагмента для отладки, нельзя как единственную систему истины. Оригинал, версия и права должны восстанавливать индекс с нуля. Иначе расхождение парсера и полезной нагрузки неизбежно.
Как сменить модель векторных представлений без простоя качества?
Собрать новый индекс или новую проекцию, писать в оба, сравнить полноту и задержку на контрольном наборе, переключить чтение, сохранить возможность отката. Смешивать векторы старой и новой модели в одном пространстве нельзя.
Как убедиться, что документ действительно удалён?
Контрольным запросом, который должен вернуть пусто, плюс проверкой реплик и политики резервных копий. Скрытие фильтром — не удаление. Для персональных данных нужен физический контур и срок сжатия графа.
Какую метрику выбрать: косинус или L2?
Ту, под которую считалась модель. Нормированные векторы часто делают косинус и скалярное произведение взаимозаменяемыми; ненормированные — нет. Смена метрики без пересчёта векторов портит порядок соседей.
Коллекция на арендатора или общий индекс с фильтром?
Крупные арендаторы и жёсткая изоляция — отдельные коллекции или сегменты. Много мелких — общий индекс с обязательным предикатом, индексом по атрибуту и запретом запросов без ключа арендатора. Гибрид моделей тоже бывает: крупные отдельно, длинный хвост вместе.
Когда pgvector уже не хватает?
Когда боевые запросы с фильтрами не держат целевые процентили после настройки индекса и железа, когда построение графа мешает OLTP, когда нужны квантование, дисковый индекс или гибрид разреженных векторов как основной путь. Число векторов само по себе — слабый критерий.
Портит ли квантование качество поиска?
Сжимает различение близких точек. На грубом проходе это приемлемо, если короткий список затем уточняется полными векторами. Максимальное сжатие без уточнения и без измерения полноты — частая регрессия.
Где делать гибридный поиск: в базе или в приложении?
Там, где оба сигнала и одни фильтры живут рядом и где вы можете измерить слияние. Движок со встроенным гибридом экономит сеть; приложение гибче в формуле слияния. Подробности слияния рангов — в статье о гибридном поиске, а не в выборе логотипа.
Дальнейшее чтение
- Векторные базы данных — короткая глава-введение: зачем индекс в корпоративном ИИ и как он связан с правами доступа.
- Почему эмбеддинги изменили корпоративный поиск — смысл векторных представлений, границы семантической близости, гибрид с точным поиском.
- Промышленная инженерия RAG — вся цепочка: корпус, разбиение, поиск, переранжирование, оценка. Этот материал — только слой хранения.
- Архитектура промышленного RAG — платформенная схема, в которой векторный индекс — один сервис среди других.
- Гибридный поиск с
BM25, векторами иreciprocal-rank fusion— как сливать лексический и векторный каналы. - Эксперименты с разбиением документов — как фрагмент, который вы кладёте в индекс, влияет на оба канала поиска.
- Python-библиотеки векторных баз — упаковка клиентов, стабильность API и путь из ноутбука, а не сравнительный тест соседей.
Заключение
Векторная база в продакшене — это индекс с контрактом, а не универсальное хранилище знаний. Контракт включает метрику и версию модели, приближенный поиск с измеримой полнотой, предикаты прав и арендатора внутри запроса, проверяемое удаление и возможность перестроить проекцию из канона.
PostgreSQL с расширением pgvector остаётся честной промышленной точкой старта, пока объём, фильтры и задержка живут в одном операционном контуре с транзакционными данными. Отдельный продукт — Qdrant, Weaviate, Pinecone, Milvus или векторный контур в OpenSearch/Elasticsearch — оправдан, когда этот контур начинает врать по процентилям, памяти или изоляции, а не когда так красивее на схеме.
Алгоритм соседей выбирают после того, как понятен запрос: какой предикат, какая полнота, какой бюджет памяти, какой ритм обновлений. Без этих четырёх чисел сравнительный тест чужого блога — развлечение. С ними слой индекса становится скучной, сопровождаемой частью платформы — и перестаёт быть местом, куда сваливают «всю RAG-магию».
В лабораторном смысле Stuzhuk Lab это тот же принцип, что и для остальной платформы: сначала доказывают, что нужный фрагмент находится и имеет право быть найденным, и только потом спорят о формулировке ответа модели.

