pgvector: indecși HNSW și IVFFlat în PostgreSQL

Extensii și pgvector pgvector 0.5.0+ (HNSW), IVFFlat din primele versiuni; scanare iterativă: 0.8.0+

Indecși pentru căutarea aproximativă a celor mai apropiați vectori: HNSW (mai precis, construcție mai lentă) și IVFFlat (construcție rapidă).

Sintaxă SQL
CREATE INDEX ON tabel USING hnsw (coloana vector_cosine_ops) [WITH (m = 16, ef_construction = 64)];
CREATE INDEX ON tabel USING ivfflat (coloana vector_l2_ops) WITH (lists = 100);
SET hnsw.ef_search = 100;
SET ivfflat.probes = 10;

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_mem mic la construirea unui index HNSW mare: construcția durează mult mai mult. pgvector afișează un NOTICE câ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.