Ce face pgvector: indecși HNSW și IVFFlat
Fără index, pgvector compară vectorul căutat cu fiecare rând: rezultat exact, dar lent la milioane de rânduri. Indecșii HNSW și IVFFlat fac o căutare aproximativă: foarte rapidă, dar pot rata uneori un vecin apropiat (recall sub 100%).
HNSW construiește un graf pe mai multe niveluri. Are cel mai bun raport viteză/precizie, se poate crea pe un tabel gol și se actualizează la inserări, dar se construiește mai lent și ocupă mai multă memorie. Parametri: m (legături per nod, implicit 16), ef_construction (implicit 64) și, la căutare, hnsw.ef_search (implicit 40).
IVFFlat împarte vectorii în lists grupuri; la căutare verifică doar ivfflat.probes grupuri (implicit 1). Se creează după ce tabelul are date. Recomandarea din documentația pgvector: lists = rânduri / 1000 până la un milion de rânduri și √rânduri peste un milion; probes în jur de √lists.
Parametri
| Parametru | Descriere |
|---|---|
vector_l2_ops / vector_cosine_ops / vector_ip_ops |
Clasa de operatori: trebuie să corespundă operatorului din ORDER BY (<->, <=>, <#>). |
m, ef_construction |
HNSW: mai mari = index mai precis, construcție mai lentă. |
hnsw.ef_search |
HNSW: câți candidați verifică o căutare (implicit 40). Mai mare = mai precis, mai lent. |
lists, ivfflat.probes |
IVFFlat: numărul de grupuri, respectiv câte grupuri verifică o căutare. |
hnsw.iterative_scan |
pgvector 0.8.0+: continuă căutarea în index când filtrele WHERE elimină prea multe rânduri. |
Ce returnează
Mesajul CREATE INDEX.
Exemple
Exemplul 1: Index HNSW pentru distanța cosinus
SET maintenance_work_mem = '2GB';
CREATE INDEX articole_embedding_idx ON articole
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
SET hnsw.ef_search = 100;
EXPLAIN (COSTS OFF)
SELECT titlu FROM articole ORDER BY embedding <=> '[3,1,1]' LIMIT 5;
Rezultat în psql (pe un tabel cu multe rânduri)
SET
CREATE INDEX
SET
QUERY PLAN
-----------------------------------------------------------
Limit
-> Index Scan using articole_embedding_idx on articole
Order By: (embedding <=> '[3,1,1]'::vector)
(3 rows)
Exemplul 2: IVFFlat creat pe un tabel aproape gol
pgvector avertizează: grupurile se calculează din datele existente, deci un index creat prea devreme are precizie slabă.
CREATE INDEX ON articole USING ivfflat (embedding vector_l2_ops) WITH (lists = 100);
Rezultat în psql
NOTICE: ivfflat index created with little data
DETAIL: This will cause low recall.
HINT: Drop the index until the table has more data.
CREATE INDEX
Exemplul 3: Căutare cu filtru și scanare iterativă (pgvector 0.8.0+)
Fără scanare iterativă, indexul returnează doar ef_search candidați, iar filtrul WHERE îi poate elimina pe aproape toți.
SET hnsw.iterative_scan = relaxed_order;
SELECT titlu
FROM articole
WHERE categorie = 'retete'
ORDER BY embedding <=> '[3,1,1]'
LIMIT 5;
Rezultat în psql
SET
titlu
-------------------
Rețete cu dovleac
Ciorbă de legume
(2 rows)
Greșeli frecvente
- Creezi indexul cu
vector_l2_opsși cauți cu<=>(cosinus): indexul nu se folosește și interogarea devine o scanare completă. - Creezi un index IVFFlat înainte de a încărca datele. Creează-l după import (sau folosește HNSW).
- Lași
maintenance_work_memmic la construirea unui index HNSW mare: construcția durează mult mai mult. pgvector afișează unNOTICEcând graful nu mai încape în memorie.
Comenzi înrudite
pgvector: tipul vector și operatorii de distanță: Extensia pgvector salvează vectori (embedding-uri) în PostgreSQL și găsește cele mai apropiate rânduri: baza căutării semantice și a aplicațiilor RAG.CREATE EXTENSION: Activează o extensie (pg_trgm, pgcrypto, vector, postgis) în baza de date curentă: tipuri, funcții și operatori noi.