Creare e gestire gli indici di vettori

Questa pagina spiega come creare e gestire gli indici vettoriali Spanner, che utilizzano la ricerca approssimativa del vicino più prossimo (ANN) e strutture basate su alberi per accelerare le ricerche di similarità vettoriale nei tuoi dati.

Spanner accelera le ricerche vettoriali approssimative del vicino più prossimo (ANN) utilizzando un indice vettoriale specializzato. Questo indice sfrutta Scalable Nearest Neighbor (ScaNN) di Google Research, un algoritmo per la ricerca dei vicini più prossimi altamente efficiente.

L'indice vettoriale utilizza una struttura ad albero per partizionare i dati e facilitare ricerche più rapide. Spanner offre configurazioni ad albero a due e tre livelli:

  • Configurazione ad albero a due livelli: i nodi foglia (num_leaves) contengono gruppi di vettori strettamente correlati insieme al loro centroide corrispondente. Il livello radice è costituito dai centroidi di tutti i nodi foglia.
  • Configurazione ad albero a tre livelli: simile nel concetto a un albero a due livelli, ma introduce un ulteriore livello di ramificazione (num_branches), da cui i centroidi dei nodi foglia vengono ulteriormente partizionati per formare il livello radice (num_leaves).

Spanner sceglie un indice per te. Tuttavia, se sai che un indice specifico funziona meglio, puoi utilizzare il suggerimento FORCE_INDEX per scegliere di utilizzare l'indice vettoriale più appropriato per il tuo caso d'uso.

Per ulteriori informazioni, consulta la sezione Estratti conto VECTOR INDEX.

Limitazioni

Crea indice vettoriale

Per ottimizzare il recupero e il rendimento di un indice vettoriale, ti consigliamo di:

  • Crea l'indice vettoriale dopo che la maggior parte delle righe con gli incorporamenti è stata scritta nel database. Potresti anche dover ricreare periodicamente l'indice vettoriale dopo aver inserito nuovi dati. Per saperne di più, consulta la sezione Ricostruire l'indice vettoriale.

  • Utilizza la clausola STORING per archiviare una copia di una colonna nell'indice vettoriale. Se un valore di colonna è memorizzato nell'indice vettoriale, Spanner esegue il filtraggio a livello di foglia dell'indice per migliorare le prestazioni delle query. Ti consigliamo di memorizzare una colonna se viene utilizzata in una condizione di filtro. Per saperne di più sull'utilizzo di STORING in un indice, vedi Creare un indice per le scansioni solo indice.

Quando crei la tabella, la colonna di incorporamento deve essere un array di tipo di dati FLOAT32 (consigliato) o FLOAT64 e deve avere un'annotazione vector_length, che indica la dimensione dei vettori.

La seguente istruzione DDL crea una tabella Documents con una colonna di incorporamento DocEmbedding con una lunghezza del vettore:

CREATE TABLE Documents (
  UserId INT64 NOT NULL,
  DocId INT64 NOT NULL,
  Author STRING (1024),
  DocContents Bytes(MAX),
  DocEmbedding ARRAY<FLOAT32>(vector_length=>128) NOT NULL,
  NullableDocEmbedding ARRAY<FLOAT32>(vector_length=>128),
  WordCount INT64,
) PRIMARY KEY (DocId);

Dopo aver compilato la tabella Documents, puoi creare un indice vettoriale con una struttura ad albero a due livelli e 1000 nodi foglia nella tabella Documents con una colonna di incorporamento DocEmbedding utilizzando la distanza del coseno:

CREATE VECTOR INDEX DocEmbeddingIndex
  ON Documents(DocEmbedding)
  STORING (WordCount)
  OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);

Se la colonna di incorporamento non è contrassegnata come NOT NULL nella definizione della tabella, devi dichiararla con una clausola WHERE COLUMN_NAME IS NOT NULL nella definizione dell'indice vettoriale, dove COLUMN_NAME è il nome della colonna di incorporamento. Per creare un indice vettoriale con un albero a tre livelli e 1.000.000 di nodi foglia nella colonna di incorporamento Nullable NullableDocEmbedding utilizzando la distanza coseno:

CREATE VECTOR INDEX DocEmbeddingThreeLevelIndex
  ON Documents(NullableDocEmbedding)
  STORING (WordCount)
  WHERE NullableDocEmbedding IS NOT NULL
  OPTIONS (distance_type = 'COSINE', tree_depth = 3, num_branches=1000, num_leaves = 1000000);

Filtrare un indice vettoriale

Puoi anche creare un indice vettoriale filtrato per trovare gli elementi più simili nel tuo database che corrispondono alla condizione di filtro. Un indice vettoriale filtrato indicizza selettivamente le righe che soddisfano le condizioni di filtro specificate, migliorando le prestazioni di ricerca.

Nel seguente esempio, la tabella Documents2 ha una colonna chiamata Category. Nella nostra ricerca vettoriale, vogliamo indicizzare la categoria "Tecnologia", quindi creiamo una colonna generata che restituisce NULL se la condizione della categoria non è soddisfatta.

CREATE TABLE Documents2 (
  DocId INT64 NOT NULL,
  Category STRING(MAX),
  NullIfFiltered BOOL AS (IF(Category = 'Tech', TRUE, NULL)) HIDDEN,
  DocEmbedding ARRAY<FLOAT32>(vector_length=>128),
) PRIMARY KEY (DocId);

Poi creiamo un indice vettoriale con un filtro. L'indice vettoriale TechDocEmbeddingIndex indicizza solo i documenti della categoria "Tecnologia".

CREATE VECTOR INDEX TechDocEmbeddingIndex
  ON Documents2(DocEmbedding)
  STORING(NullIfFiltered)
  WHERE DocEmbedding IS NOT NULL AND NullIfFiltered IS NOT NULL
  OPTIONS (...);

Quando Spanner esegue la seguente query, che ha filtri che corrispondono a TechDocEmbeddingIndex, sceglie automaticamente ed è accelerata da TechDocEmbeddingIndex. La query cerca solo documenti nella categoria "Tecnologia". Puoi anche utilizzare {@FORCE_INDEX=TechDocEmbeddingIndex} per forzare Spanner a utilizzare TechDocEmbeddingIndex in modo esplicito.

SELECT *
FROM Documents2
WHERE DocEmbedding IS NOT NULL AND NullIfFiltered IS NOT NULL
ORDER BY APPROX_(....)
LIMIT 10;

Passaggi successivi