Questa pagina descrive come trovare i vicini più vicini approssimativi (ANN), creare indici di vettori e eseguire query sugli embedding di vettori utilizzando le seguenti funzioni di distanza ANN in Spanner:
APPROX_COSINE_DISTANCE
APPROX_EUCLIDEAN_DISTANCE
APPROX_DOT_PRODUCT
Quando un set di dati è piccolo, puoi utilizzare la tecnica K-Nearest Neighbor (KNN) per trovare i vettori k-nearest esatti. Tuttavia, con l'aumento del set di dati, aumentano anche la latenza e il costo di una ricerca KNN. Puoi utilizzare le ANN per trovare i vicini più prossimi approssimativi con latenza e costi notevolmente ridotti.
Vicini k più prossimi approssimativi
In una ricerca ANN, i vettori restituiti da k non sono i veri vicini più prossimi di k. A volte vengono restituiti alcuni vettori che non sono tra i k più vicini. Questo fenomeno è noto come perdita di richiamo. La quantità di perdita di richiamo accettabile dipende dal caso d'uso, ma nella maggior parte dei casi, perdere un po' di richiamo in cambio di un miglioramento delle prestazioni del database è un compromesso accettabile.
Per ulteriori dettagli sulle funzioni di distanza approssimativa di Spanner, consulta:
APPROX_COSINE_DISTANCE
in GoogleSQLAPPROX_EUCLIDEAN_DISTANCE
in GoogleSQLAPPROX_DOT_PRODUCT
in GoogleSQL
Indice vettoriale
Spanner accelera le ricerche di vettori ANN utilizzando un indice vettoriale specializzato. Questo indice sfrutta Scalable Nearest Neighbor (ScaNN) di Google Research, un algoritmo di ricerca del vicino più prossimo altamente efficiente.
L'indice di vettori utilizza una struttura basata su albero per partizionare i dati e semplificare le ricerche. Spanner offre configurazioni ad albero sia a due che a tre livelli:
- Configurazione ad albero a due livelli: i nodi foglia (
num_leaves
) contengono gruppi di vettori correlati e il loro centroide corrispondente. Il livello radice è costituito dai centroidi di tutti i nodi foglia. - Configurazione ad albero a tre livelli: simile per concetto a un albero a due livelli, ma con l'introduzione di un livello aggiuntivo di rami (
num_branches
), da cui i centroidi dei nodi a foglia vengono ulteriormente suddivisi per formare il livello principale (num_leaves
).
Inoltre, devi creare l'indice di vettori con una metrica di distanza specifica.
Puoi scegliere la metrica della distanza più adatta al tuo caso d'uso impostando distance_type
su COSINE
, DOT_PRODUCT
o EUCLIDEAN
.
Per ulteriori informazioni, consulta le dichiarazioni VECTOR INDEX
.
Limitazioni
L'indice di vettori Spanner presenta le seguenti limitazioni:
ALTER VECTOR INDEX
non è supportato.
Crea indice di vettori
Per ottimizzare al meglio l'indice di vettori in modo da ottenere un buon recupero e un buon rendimento, ti consigliamo di creare l'indice di vettori dopo che la maggior parte delle righe con gli embedding è stata scritta nel database. Potresti anche dover ricostruire periodicamente l'indice del vettore dopo aver inserito nuovi dati. Per ulteriori informazioni, consulta Rigenerare l'indice del vettore.
Per creare un indice vettoriale con un albero a due livelli e 1000 nodi a foglia in una tabella Documents
con una colonna di embedding DocEmbedding
utilizzando la distanza di cosine:
CREATE VECTOR INDEX DocEmbeddingIndex
ON Documents(DocEmbedding)
OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);
Per creare un indice di vettori con un albero a tre livelli e 1000000 nodi foglia:
CREATE VECTOR INDEX DocEmbeddingIndex
ON Documents(NullableDocEmbedding)
WHERE NullableDocEmbedding IS NOT NULL
OPTIONS (distance_type = 'COSINE', tree_depth = 3, num_branches=1000, num_leaves = 1000000);
Se la colonna di incorporamento è nullable, devi dichiararla con una clausola WHERE column_name IS NOT NULL
:
CREATE VECTOR INDEX DocEmbeddingIndex
ON Documents(NullableDocEmbedding)
WHERE NullableDocEmbedding IS NOT NULL
OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);
Esegui query sugli embedding vettoriali
Per eseguire una query su un indice di vettori, utilizza una delle tre funzioni di distanza approssimativa:
APPROX_COSINE_DISTANCE
APPROX_EUCLIDEAN_DISTANCE
APPROX_DOT_PRODUCT
Le limitazioni relative all'utilizzo delle funzioni di distanza approssimativa includono quanto segue:
- Devi fornire un suggerimento di query per utilizzare l'indice vettoriale.
- Devi utilizzare un'espressione costante come argomento della funzione di distanza (ad esempio un parametro o un valore letterale).
- La query o la sottoquery in cui viene utilizzata la funzione di distanza approssimativa deve avere una forma specifica: la funzione di distanza deve essere l'unica chiave
ORDER BY
e deve essere specificato un limite.
Per un elenco dettagliato delle limitazioni, consulta la pagina di riferimento della funzione di distanza approssimativa.
Esempio
Per cercare i 100 vettori più vicini a [1.0, 2.0, 3.0]
:
SELECT DocId
FROM Documents@{FORCE_INDEX=DocEmbeddingIndex}
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
ARRAY<FLOAT32>[1.0, 2.0, 3.0], DocEmbedding,
options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100
Se la colonna di incorporamento ammette valori nulli:
SELECT DocId
FROM Documents@{FORCE_INDEX=DocEmbeddingIndex}
WHERE NullableDocEmbedding IS NOT NULL
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
ARRAY<FLOAT32>[1.0, 2.0, 3.0], NullableDocEmbedding,
options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100
Best practice
Segui queste best practice per ottimizzare gli indici di vettori e migliorare i risultati delle query.
Ottimizza le opzioni di ricerca vettoriale
Il valore di ricerca di vettori più ottimale dipende dal caso d'uso, dal set di dati di vettori e dai vettori di query. Potresti dover eseguire l'ottimizzazione iterativa per trovare i valori migliori per il tuo carico di lavoro specifico.
Ecco alcune linee guida utili da seguire per scegliere valori appropriati:
tree_depth
(livello dell'albero): se la tabella da indicizzare ha meno di 10 milioni di righe, utilizza un valoretree_depth
pari a2
. In caso contrario, untree_depth
di3
supporta tabelle fino a circa 10 miliardi di righe.num_leaves
: utilizza la radice quadrata del numero di righe nel set di dati. Un valore più elevato può aumentare il tempo di compilazione dell'indice di vettori. Evita di impostare un valore dinum_leaves
superiore atable_row_count/1000
, in quanto si ottengono foglie troppo piccole e un rendimento scadente.num_leaves_to_search
: questa opzione specifica il numero di nodi foglia dell'indice sottoposti a ricerca. L'aumento dinum_leaves_to_search
migliora il richiamo, ma aumenta anche la latenza e i costi. Ti consigliamo di utilizzare un numero pari all'1% del numero totale di foglie definito nell'istruzioneCREATE VECTOR INDEX
come valore pernum_leaves_to_search
. Se utilizzi una clausola di filtro, aumenta questo valore per ampliare la ricerca.
Se viene raggiunto un livello di recupero accettabile, ma il costo delle query è troppo elevato,
con un QPS massimo ridotto, prova ad aumentare num_leaves
seguendo questi
passaggi:
- Imposta
num_leaves
su un multiplo k del suo valore originale (ad esempio2 * sqrt(table_row_count)
). - Imposta
num_leaves_to_search
come lo stesso multiplo k del valore originale. - Prova a ridurre
num_leaves_to_search
per migliorare il costo e il QPS mantenendo il richiamo.
Migliorare il ricordo
Esistono diverse possibilità di peggioramento del richiamo, tra cui:
num_leaves_to_search
è troppo piccolo: potresti riscontrare difficoltà a trovare i vicini più prossimi per alcuni vettori di query, quindi aumentarenum_leaves_to_search
per cercare più foglie può contribuire a migliorare il richiamo. Le query recenti potrebbero aver iniziato a contenere più di questi vettori problematici.L'indice di vettori deve essere ricostruito: la struttura ad albero dell'indice di vettori è ottimizzata per il set di dati al momento della creazione ed è statica in seguito. Pertanto, se vengono aggiunti vettori notevolmente diversi dopo la creazione dell'indice iniziale dei vettori, la struttura ad albero potrebbe non essere ottimale, con un conseguente peggioramento del recupero.
Ricostruisci l'indice di vettori
Per ricostruire l'indice di vettori senza tempi di inattività:
- Crea un nuovo indice vettoriale nella stessa colonna di embedding dell'indice vettoriale corrente, aggiornando i parametri (ad es.
OPTIONS
) in base alle esigenze. - Al termine della creazione dell'indice, modifica l'suggerimento
FORCE_INDEX
in modo che indichi il nuovo indice per aggiornare la query di ricerca di vettori. In questo modo, la query utilizzerà il nuovo indice di vettori. Potresti anche dover eseguire nuovamente l'accordaturanum_leaves_to_search
nella nuova query. - Elimina l'indice vettoriale obsoleto.
Passaggi successivi
Scopri di più sulle funzioni
APPROXIMATE_COSINE_DISTANCE()
,APPROXIMATE_EUCLIDEAN_DISTANCE()
,APPROXIMATE_DOT_PRODUCT()
di GoogleSQL.Scopri di più sulle istruzioni
VECTOR INDEX
di GoogleSQL.