pgvector: полный обзор

Что pgvector добавляет в PostgreSQL: расстояния, индексы и типы, сравнение с векторными базами, три примера SQL, настройки для рабочего проекта и частые ошибки.

Стек и технологии Обновлено

Коротко

pgvector — расширение для PostgreSQL, которое добавляет тип для векторов, операторы расстояния и индексы для быстрого поиска похожего. Оно превращает обычную базу в хранилище для поиска по смыслу, рекомендаций и RAG: векторы живут в той же таблице, что и товары, статьи или обращения, фильтруются обычным SQL, соединяются с другими таблицами и попадают в резервные копии вместе со всем остальным. Большинству проектов — до десятков миллионов векторов — отдельная векторная база не нужна. Расширение есть в основных управляемых сервисах PostgreSQL и ставится на свой сервер одним пакетом.

pgvector коротко

Главные факты одной таблицей: что добавляет расширение и где оно работает.

Что это
Расширение PostgreSQL с открытым кодом для хранения векторов и поиска по ним
История
Эндрю Кейн, 2021 год; индексы HNSW с версии 0.5 (2023), итеративный поиск с 0.8 (2024)
Лицензия
Лицензия PostgreSQL — бесплатно, в том числе для коммерции
Типы
vector, halfvec (вдвое меньше), sparsevec, bit
Индексы
HNSW и IVFFlat — приближённый поиск
Где работает
Свой сервер, AWS, Google Cloud, Azure, Supabase, Neon и другие сервисы
Комфортный масштаб
До десятков миллионов векторов на одном сервере

Расстояния, индексы и типы

Всё, что pgvector добавляет в SQL. Расстояние в запросе должно совпадать с классом операторов индекса, иначе индекс не используется.

ЭлементЧто этоКогда брать
<=> косинусное расстояние эмбеддинги текста — обычный выбор
<-> евклидово расстояние (L2) картинки, координаты, некоторые модели
<#> отрицательное скалярное произведение нормированные векторы — быстрее всего
<+> манхэттенское расстояние (L1) редкие особые случаи
HNSW индекс-граф: быстрый и точный по умолчанию для большинства проектов
IVFFlat индекс кластеров: меньше, строится быстрее большие неизменные наборы, после загрузки данных
halfvec векторы половинной точности вдвое меньше памяти почти без потери качества
bit двоичные векторы с расстоянием Хэмминга быстрый первый проход по очень большим наборам

pgvector или отдельная векторная база

Pinecone, Qdrant, Weaviate и Milvus созданы только для векторов. Вот что это даёт и чего стоит.

КритерийpgvectorВекторная база
Где живут векторы рядом с данными, в той же таблице в отдельном сервисе
Синхронизация не нужна — одна транзакция нужна, источник расхождений
Фильтры обычный SQL, соединения свой язык фильтров
Поиск по словам полнотекстовый поиск PostgreSQL зависит от продукта
Копии и права те же, что у всей базы настраиваются отдельно
Масштаб десятки миллионов векторов до миллиардов
Стоимость ничего сверху отдельный счёт или серверы

Как выглядит pgvector: 3 примера

Таблица с индексом, поиск с фильтром и гибридный поиск по смыслу и по словам. Вектор вопроса считает приложение и передаёт параметром.

Таблица и индекс

Вектор — просто ещё одна колонка; индекс HNSW строится под косинусное расстояние.

schema.sql
-- pgvector: векторы живут в обычной таблице рядом с остальными данными
CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE products (
    id        bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    sku       text UNIQUE NOT NULL,
    title     text NOT NULL,
    category  text NOT NULL,
    in_stock  boolean NOT NULL DEFAULT true,
    embedding vector(1024)   -- размер задаёт модель эмбеддингов
);

-- Индекс HNSW для косинусного расстояния: быстрый приближённый поиск
CREATE INDEX products_embedding_idx
    ON products USING hnsw (embedding vector_cosine_ops);

Поиск с фильтром

Обычные условия WHERE рядом со сходством; итеративный поиск не даёт выдаче опустеть при строгом фильтре.

search.sql
-- Похожие товары в наличии; вектор запроса приходит из приложения как $1
SET hnsw.iterative_scan = relaxed_order;  -- pgvector 0.8+: искать дальше, пока фильтр отбрасывает строки

SELECT sku, title, 1 - (embedding <=> $1) AS similarity
FROM products
WHERE in_stock AND category = 'tables'
ORDER BY embedding <=> $1
LIMIT 10;

Гибридный поиск

Смысл находит «обеденный стол» по запросу «стол на кухню», слова — точный артикул, вместе — и то и другое.

hybrid.sql
-- Гибридный поиск: по смыслу (pgvector) и по словам (полнотекстовый поиск),
-- два списка объединяются по местам — Reciprocal Rank Fusion
WITH semantic AS (
    SELECT id, row_number() OVER (ORDER BY embedding <=> $1) AS rank
    FROM products
    ORDER BY embedding <=> $1
    LIMIT 20
),
keyword AS (
    SELECT id, row_number() OVER (ORDER BY ts_rank_cd(to_tsvector('russian', title), q) DESC) AS rank
    FROM products, plainto_tsquery('russian', $2) AS q
    WHERE to_tsvector('russian', title) @@ q
    ORDER BY ts_rank_cd(to_tsvector('russian', title), q) DESC
    LIMIT 20
)
SELECT p.sku, p.title,
       coalesce(1.0 / (60 + s.rank), 0) + coalesce(1.0 / (60 + k.rank), 0) AS score
FROM semantic s
FULL OUTER JOIN keyword k ON k.id = s.id
JOIN products p ON p.id = coalesce(s.id, k.id)
ORDER BY score DESC
LIMIT 10;

7 настроек, которые важны в рабочем проекте

  1. 01

    Индекс совпадает с оператором

    Индекс на vector_cosine_ops работает только для <=>; план проверяют через EXPLAIN.

  2. 02

    ef_search для точности

    hnsw.ef_search (по умолчанию 40) поднимают, когда в выдаче не хватает нужного.

  3. 03

    Память на построение

    Больший maintenance_work_mem строит индекс HNSW в разы быстрее.

  4. 04

    halfvec для больших наборов

    Вдвое уменьшает таблицу и индекс почти без потери качества.

  5. 05

    Итеративный поиск с фильтрами

    Без него строгий WHERE может вернуть меньше строк, чем LIMIT.

  6. 06

    Частичные индексы

    Отдельный индекс на язык или категорию, когда поиск никогда их не пересекает.

  7. 07

    Одна модель на колонку

    Векторы разных моделей несравнимы — новая модель означает новую колонку и переиндексацию.

Частые ошибки с pgvector

  1. Отдельная векторная база раньше времени

    Ещё один сервис и синхронизация ради нескольких сотен тысяч векторов, которые PostgreSQL держит легко.

  2. Нет индекса

    Без него каждый запрос сравнивает вопрос со всеми строками — терпимо на тысячах, медленно на миллионах.

  3. IVFFlat на пустой таблице

    Его кластеры считаются по имеющимся данным; построенный слишком рано, он плохо ищет.

  4. Сходство без порога

    ORDER BY всегда вернёт ближайшие строки, даже если ни одна не подходит.

  5. Смешивать модели

    Часть строк проиндексирована одной моделью, часть другой — поиск молча портится.

  6. Векторы без исходного текста

    Текст хранят рядом с вектором — чтобы показать, процитировать и переиндексировать.

Вопросы о pgvector

Что такое pgvector?

Расширение, которое позволяет PostgreSQL хранить векторы и искать самые похожие.

Сколько векторов он выдержит?

Десятки миллионов на одном сервере с индексом HNSW; дальше — секционирование или специализированная система.

HNSW или IVFFlat?

HNSW в большинстве случаев: он точнее и работает на таблице, которая постоянно меняется.

Какой размер вектора нужен?

Тот, что выдаёт модель эмбеддингов, — 384, 768, 1024, 1536 и так далее.

Есть ли он в управляемом PostgreSQL?

Да, в AWS, Google Cloud, Azure, Supabase, Neon и большинстве других сервисов.

Работает ли он с MySQL?

Нет, это расширение PostgreSQL; у MySQL в последних версиях свой тип для векторов.

Можно ли искать по картинкам?

Да, если картинки превращены в векторы подходящей моделью; базе неважно, что означает вектор.

Форма

Поиск
по смыслу

Делаю поиск по смыслу, рекомендации и ИИ-ассистентов на PostgreSQL с pgvector — рядом с вашими данными, без отдельного сервиса. Расскажите о проекте — отвечу в течение рабочего дня.

Или пишите на [email protected]