Семантичний пошук знаходить документи за змістом, а не за збігом слів: запит «як не втратити завдання при падінні воркера» знайде статтю про повторні спроби в чергах, навіть без спільних слів.
Текст перетворюють на вектор-ембединг (масив з сотень чи тисяч чисел) за допомогою моделі (OpenAI, Voyage, локальні моделі). Схожі за змістом тексти мають близькі вектори.
Розширення pgvector додає тип vector і оператори відстані:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE documents (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
content text NOT NULL,
embedding vector(1536)
);
-- 5 найближчих за косинусною відстанню
SELECT id, content
FROM documents
ORDER BY embedding <=> $1
LIMIT 5;
Оператори: <-> - евклідова відстань, <=> - косинусна, <#> - від'ємний скалярний добуток.
Індекси для наближеного пошуку (ANN) - точний пошук перебирає всі вектори, на мільйонах це повільно:
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);
- HNSW - швидкий і точний пошук, але повільніша побудова й більше пам'яті.
- IVFFlat - швидша побудова, менше пам'яті, але потрібні дані для навчання (створювати після наповнення таблиці) і нижча точність.
Наближені індекси можуть пропустити частину справжніх сусідів - точність регулюється параметрами (hnsw.ef_search).
Переваги вектора в PostgreSQL:
- Векторний пошук в одному запиті з фільтрами (
WHERE tenant_id = ? AND published) і транзакційними даними. - Немає окремої векторної бази, її синхронізації й бекапів.
Практичні нюанси:
- Гібридний пошук: поєднання векторного й повнотекстового пошуку (наприклад, через Reciprocal Rank Fusion) зазвичай дає кращі результати, ніж кожен окремо.
- Фільтри з HNSW: при дуже вибірковому фільтрі індекс може повернути замало результатів - нові версії pgvector мають ітеративне сканування для цього випадку.
- Ембединги прив'язані до моделі: змінили модель - перераховуйте всі вектори.
- Розмір: вектор на 1536 значень - ~6 КБ на рядок, плюс індекс.