PRODPiattaforma BaaS europea sovranaApri Dashboard →

IA nativa · 9 lettura minima

Indice HNSW in Postgres: indice bene per la ricerca vettoriale

Affane Daylami · Fondateur · 6 aprile 2026

Torniamo al blog

HNSW è l'algoritmo di indicizzazione consigliato da pgvector per la ricerca di vettori di somiglianza su Postgres. Questa guida mostra come creare un indice HNSW correttamente ottimizzato. Tre scelte contano: il tipo di colonna in base alla dimensione dei tuoi incorporamenti, i parametri m ed ef_construction durante la costruzione ed ef_search ad ogni richiesta per arbitrare il richiamo e la latenza.

Questo testo inglese è stato generato automaticamente dall'originale francese e non è stato ancora rivisto.
Questa pagina è stata tradotta automaticamente. Fa fede la versione inglese.

La ricerca vettoriale nativa di Aurabase (RAG, pgvector, embedding) si basa su questo stesso meccanismo di indicizzazione, descritto in dettaglio nella pagina Native AI su Postgres. Questa guida presuppone una tabella Postgres con pgctor già installato, una colonna di tipo vectore almeno qualche migliaio di righe. Di seguito, una semplice scansione sequenziale è spesso più veloce di un indice approssimativo.

L'essenziale

  • HNSW non richiede alcuna fase di training, a differenza di IVFFlat: l'indice è costruito per inserimenti, disponibile in pgvector dalla versione 0.5.0.
  • Due parametri impostano la qualità dell'indice in costruzione: m (connessioni per nodo, default 16) e ef_construction (larghezza di ricerca in costruzione, default 64).
  • Un terzo parametro, hnsw.ef_search (predefinito pgctor: 40), viene modificato per ogni richiesta, senza ricostruire l'indice, per arbitrare il richiamo e la latenza.
  • pgvector limita l'indicizzazione HNSW di tipo vector a 2000 dimensioni. Oltre a ciò (un incorporamento con 3072 dimensioni, ad esempio), è necessario un cast su halfvec per indicizzare.
  • pgvector 0.8.6 è la versione incorporata nell'immagine tenant di Aurabase Postgres, verificata direttamente nel Dockerfile il 24 agosto 2026.
#
Capire

Cos'è un indice HNSW in pgvector?

HNSW sta per Hierarchical Navigable Small World. Si tratta di un indice grafico: ogni vettore diventa un nodo connesso ai suoi vicini più prossimi, organizzati in più strati sovrapposti. La ricerca inizia nella parte superiore del grafico, sullo strato più scarso, per poi scendere strato dopo strato fino ai vicini più rilevanti. Il tempo di ricerca diventa quindi quasi logaritmico, non lineare rispetto al numero di righe.

IVFFlat, l'altro indice di pgvector, funziona diversamente: divide lo spazio vettoriale in liste determinate da un passaggio di training su un campione esistente, prima di poter indicizzare qualsiasi cosa. HNSW non ha questo vincolo, ogni inserimento arricchisce direttamente il grafico, il che rende più semplice operare su una tabella che cresce continuamente. D'altra parte, un indice HNSW consuma più memoria e richiede più tempo per la creazione rispetto a un IVFFlat equivalente sullo stesso volume.

pgvector introduce il supporto HNSW nella versione 0.5.0. Le versioni successive aggiungono funzionalità utili per questa guida: il tipo halfvec (0.7.0) per indicizzare oltre 2000 dimensioni e il parametro hnsw.iterative_scan (0.8.0) per migliorare il richiamo delle query filtrate. Se confronti pgvector con una base vettoriale dedicata prima di decidere, il nostro confronto pgvector vs Pinecone, Weaviate e Qdrant descrive in dettaglio i compromessi.

#
Passaggio 1

Controlla la tua versione di pgvector prima di creare l'indice

Conferma prima la versione di pgvector installata. Un'estensione troppo vecchia causa il mancato funzionamento silenzioso di alcune funzionalità di questa guida, in particolare halfvec e hnsw.iterative_scan.

psqlsql
SELECT extversion FROM pg_extension WHERE extname = 'vector';

HNSW esiste da pgvector 0.5.0. Il tipo halfvec, necessario per indicizzare gli incorporamenti oltre le 2000 dimensioni, richiede almeno la versione 0.7.0. Il parametro hnsw.iterative_scan richiede la versione 0.8.0.

Sui progetti Aurabase, la domanda non si pone: l'immagine Postgres incorpora pgvector 0.8.6, sia sul cluster Postgres condiviso (docker/Postgres.Dockerfile, costruito direttamente su pgvector/pgvector:0.8.6-pg16-bookworm) sia sulle istanze CNPG Postgres 16 dedicate per progetto (docker/Postgres.CNPG.Dockerfile, che eredita pgvector 0.8.6 dall'immagine ufficiale CloudNativePG). Verificato in entrambi i Dockerfile il 24 agosto 2026.

#
Passaggio 2

Scegli il giusto tipo di colonna in base alla dimensione dei tuoi incorporamenti

Il tipo di colonna dipende dalla dimensione degli incorporamenti, non solo dal modello che li genera. pgvector memorizza un vettore classico nel tipo vector, con un limite di 16.000 dimensioni in memoria. Ma l'indicizzazione HNSW su questo tipo è limitata a 2000 dimensioni: oltre queste, CREATE INDEX fallisce.

I modelli di incorporamento comuni spesso superano questa soglia: text-embedding-3-large di OpenAI o gemini-embedding-2 di Google producono nativamente fino a 3072 dimensioni. Per indicizzare questi vettori con HNSW, eseguire il cast della colonna su halfvec (precisione di archiviazione dimezzata), che spinge il limite di indicizzazione ben oltre le 2000 dimensioni.

DimensioniColonnaHNSW sul vettoreRichiede il casting
768incorporamento_768SìNo
1536incorporamento_1536SìNo
3072incorporamento_3072No (> 2000 dim)Sì, lancia::halfvec(3072)

Il motore RAG di Aurabase illustra questo compromesso in produzione: tre classi di dimensioni supportate (768, 1536, 3072), memorizzate in tre colonne distinte della stessa tabella embeddings. Le colonne 768 e 1536 sono indicizzate direttamente in HNSW nel tipo vector. La colonna 3072 è indicizzata tramite un cast ::halfvec(3072), proprio per aggirare il limite di dimensione 2000.

migration.sqlsql
CREATE INDEX idx_embeddings_vec_768 ON embeddings
  USING hnsw (embedding_768 vector_cosine_ops)
  WHERE embedding_768 IS NOT NULL;

CREATE INDEX idx_embeddings_vec_1536 ON embeddings
  USING hnsw (embedding_1536 vector_cosine_ops)
  WHERE embedding_1536 IS NOT NULL;

CREATE INDEX idx_embeddings_vec_3072 ON embeddings
  USING hnsw ((embedding_3072::halfvec(3072)) halfvec_cosine_ops)
  WHERE embedding_3072 IS NOT NULL;

Per i dettagli sull'acquisizione (chunking, chiamata al provider di incorporamento, inserimento), vedere il tutorial sulla pipeline RAG su pgvector.

#
Passaggio 3

Crea l'indice con i parametri m ed ef_construction

La sintassi minima è sufficiente per un primo indice, con i valori predefiniti di pgvettoriale.

psqlsql
CREATE INDEX ON items
  USING hnsw (embedding vector_cosine_ops);

pgvector applica quindi m = 16 e ef_construction = 64. Per modificare esplicitamente questi valori, utilizzare la clausola WITH:

psqlsql
CREATE INDEX ON items
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 24, ef_construction = 100);
Accelerare una costruzione importante

Prima di costruire un indice HNSW su una tabella di grandi dimensioni, aumentare temporaneamente maintenance_work_mem per la sessione: questa è, secondo la stessa documentazione di pgvector, la leva più diretta per ridurre i tempi di costruzione.

Cosa cambia il parametro m?

m imposta il numero massimo di connessioni che ciascun nodo nel grafico mantiene per livello. Un valore più alto densifica il grafico: aumenta il ricordo, ma aumentano, in modo approssimativamente lineare, anche la memoria consumata e il tempo di costruzione. Il valore predefinito (16) è adatto alla maggior parte dei casi. Aumentare a 24 o 32 è particolarmente giustificato su grandi inglobamenti, dove la distinzione tra vicini vicini e lontani diventa più sottile.

Cosa cambia ef_construction?

ef_construction imposta la dimensione dell'elenco di candidati esplorato durante la costruzione dell'indice, per ciascun nodo inserito. Un valore più alto migliora la qualità del grafico finale, quindi l'eventuale richiamo, a costo di un tempo di realizzazione più lungo. A differenza di m, questo parametro non ha alcun costo al momento della query: è un investimento una tantum, pagato una sola volta al momento della creazione dell'indice.

Indici parziali per diverse classi di dimensioni nella stessa tabella

Quando una tabella memorizza più colonne vettoriali (una per classe di dimensione, come fa Aurabase), indicizza ciascuna colonna separatamente con una clausola WHERE colonne IS NOT NULL. Questo indice parziale evita di indicizzare righe vuote per classi non utilizzate da una determinata riga, riducendo la dimensione dell'indice e velocizzandone la costruzione senza costare nulla nel richiamo.

La scelta della classe dell'operatore (vector_cosine_ops, vector_l2_ops o vector_ip_ops) deve corrispondere alla metrica su cui è stato addestrato il modello di incorporamento. I modelli di incorporamento del testo più recenti sono addestrati per la somiglianza del coseno: vector_cosine_ops (o halfvec_cosine_ops su una colonna cast) è quindi la scelta predefinita più sicura.

#
Passaggio 4

Imposta ef_search al momento della query

ef_search viene impostato su ogni query, non quando viene creato l'indice. Stabilisce la dimensione della lista di candidati esplorati durante la ricerca: più è alta, migliore è il richiamo, a scapito di una latenza più lunga. pgvector imposta il suo valore predefinito su 40.

psqlsql
SET LOCAL hnsw.ef_search = 100;

SELECT id, content
FROM embeddings
ORDER BY embedding <=> '[...]'::vector
LIMIT 10;

40 è raramente sufficiente non appena una query combina la ricerca vettoriale con un filtro WHERE applicato dopo la scansione dell'indice (su uno spazio dei nomi, un tenant o qualsiasi altro criterio di metadati). La scansione HNSW riporta ef_search candidati grezzi, quindi il filtro ne scarta una parte. Se sopravvivono troppo pochi candidati, il LIMIT finale risulta insufficiente.

Il motore Aurabase RAG espande quindi ef_search dinamicamente in base al top_krichiesto, invece di mantenere il valore fisso di 40: ef = max(top_k × 4, 64). Una ricerca per i 5 risultati più vicini utilizza ef_search = 64; una ricerca dei primi 50 utilizza ef_search = 200. Questa formula rimane regolabile in base alla variabile di ambiente per le distribuzioni che necessitano di un altro compromesso tra richiamo e latenza.

pgvector 0.8 aggiunge una seconda leva per questo stesso problema: hnsw.iterative_scan. Nella modalità strict_order o relaxed_order, la ricerca amplia gradualmente la ricerca fino a raccogliere risultati sufficienti dopo il filtraggio, anziché fermarsi su un elenco fisso di candidati. Aurabase lo attiva per impostazione predefinita in strict_order, ma protegge la chiamata in un punto di salvataggio. Su una versione di pgvector precedente alla 0.8, dove questo parametro non esiste, la query continua in modalità degradata anziché fallire.

#
Vai oltre

Costruisci la pipeline RAG completa

Questo indice HNSW è solo una parte della pipeline RAG completa: suddivisione in blocchi, generazione di incorporamento, inserimento e quindi ricerca. Il nostro tutorial passo passo costruisce questa pipeline end-to-end su pgvector, dal primo inserimento alla query di somiglianza. La documentazione tecnica descrive inoltre in dettaglio tutte le funzionalità AI native di Aurabase basate su Postgres.

#
Domande frequenti

Domande frequenti

HNSW o IVFFlat: quale scegliere con pgvector?+
HNSW è adatto alla stragrande maggioranza dei casi di ricerca vettoriale in produzione: migliore richiamo a parità di latenza, nessuna fase di addestramento preliminare e buona tolleranza alle tabelle che crescono continuamente. IVFFlat rimane rilevante quando la memoria disponibile è molto limitata, al prezzo di un richiamo generalmente inferiore e di una riqualificazione necessaria se la distribuzione dei dati cambia in modo significativo.
Quanta memoria pianificare per un indice HNSW?+
L'ordine di grandezza dipende direttamente da m e dal numero di vettori indicizzati: ogni nodo memorizza fino a m connessioni per strato, oltre al vettore stesso. Per una stima affidabile del volume effettivo, crea l'indice su un sottoinsieme rappresentativo dei tuoi dati. Quindi misura la sua dimensione con pg_relation_size() invece di fare affidamento su una regola empirica non misurata.
Possiamo indicizzare incorporamenti di più di 2000 dimensioni con HNSW?+
Non direttamente sul tipo vettore: pgvector rifiuta di costruire un indice HNSW oltre le 2000 dimensioni su questo tipo. La soluzione è eseguire il cast della colonna su halfvec al momento della creazione dell'indice, il che spinge il limite di indicizzazione dimezzando la precisione di archiviazione. Questo è esattamente l'approccio utilizzato nella produzione della classe di incorporamento a 3072 dimensioni di Aurabase.

PRONTO PER L'IMPLEMENTAZIONE?

Il tuo backend in cinque minuti.

Nessuna carta di credito richiesta · 500 MB gratuiti · 50.000 MAU