En esta página, se describe cómo encontrar vecinos aproximados más cercanos (ANN) y consultar embeddings de vectores con las funciones de distancia de ANN.
Cuando un conjunto de datos es pequeño, puedes usar K-vecinos más cercanos (KNN) para encontrar los vectores k-más cercanos exactos. Sin embargo, a medida que crece tu conjunto de datos, también aumentan la latencia y el costo de una búsqueda de KNN. Puedes usar ANN para encontrar los k-vecinos más cercanos aproximados con una latencia y un costo significativamente reducidos.
En una búsqueda de ANN, los vectores k que se muestran no son los k-vecinos más cercanos verdaderos porque la búsqueda de ANN calcula distancias aproximadas y es posible que no examine todos los vectores del conjunto de datos. En ocasiones, se muestran algunos vectores que no se encuentran entre los k-vecinos más cercanos. Esto se conoce como pérdida de recuperación. La cantidad de pérdida de recuperación que es aceptable para ti depende del caso de uso, pero, en la mayoría de los casos, perder un poco de recuperación a cambio de un mejor rendimiento de la base de datos es una compensación aceptable.
Para obtener más detalles sobre las funciones de distancia aproximada compatibles con Spanner, consulta las siguientes páginas de referencia para tu dialecto de base de datos:
- GoogleSQL
- PostgreSQL
Consulta embeddings de vectores
Spanner acelera las búsquedas de vectores de vecinos aproximados más cercanos (ANN) mediante el uso de un índice de vectores. Puedes usar un índice de vectores para consultar embeddings de vectores. Para consultar embeddings de vectores, debes primero crear un índice de vectores. Luego, puedes usar cualquiera de las tres funciones de distancia aproximada para encontrar el ANN.
Las restricciones cuando se usan las funciones de distancia aproximada incluyen lo siguiente:
- La función de distancia aproximada debe calcular la distancia entre una columna de incorporación y una expresión constante (por ejemplo, un parámetro o un literal).
- El resultado de la función de distancia aproximada se debe usar en una cláusula
ORDER BYcomo la única clave de ordenamiento, y se debe especificar unLIMITdespués deORDER BY. - La consulta debe filtrar de forma explícita las filas que no están indexadas. En la mayoría de los casos,
esto significa que la consulta debe incluir una
WHERE <column_name> IS NOT NULLcláusula que coincida con la definición del índice de vectores, a menos que la columna ya esté marcada comoNOT NULLen la definición de la tabla.
Para obtener una lista detallada de las limitaciones, consulta la página de referencia de la función de distancia aproximada.
Ejemplos
Considera una tabla Documents que tiene una columna DocEmbedding de embeddings de texto precalculadas
de la columna de bytes DocContents y una columna
NullableDocEmbedding propagada desde otras fuentes que podrían ser nulas.
GoogleSQL
CREATE TABLE Documents (
UserId INT64 NOT NULL,
DocId INT64 NOT NULL,
Author STRING(1024),
DocContents BYTES(MAX),
DocEmbedding ARRAY<FLOAT32> NOT NULL,
NullableDocEmbedding ARRAY<FLOAT32>,
WordCount INT64
) PRIMARY KEY (UserId, DocId);
PostgreSQL
CREATE TABLE documents (
user_id bigint not null,
doc_id bigint not null,
author varchar(1024),
doc_contents bytea,
doc_embedding float4[] not null,
nullable_doc_embedding float4[],
word_count bigint,
PRIMARY KEY (user_id, doc_id)
);
Para buscar los 100 vectores más cercanos a [1.0, 2.0, 3.0]:
GoogleSQL
SELECT DocId
FROM Documents
WHERE WordCount > 1000
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
ARRAY<FLOAT32>[1.0, 2.0, 3.0], DocEmbedding,
options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100
PostgreSQL
SELECT doc_id
FROM documents
WHERE word_count > 1000
ORDER BY spanner.approx_euclidean_distance(
ARRAY[1.0, 2.0, 3.0]::float4[], doc_embedding,
options=>jsonb'{"num_leaves_to_search": 10}'
)
LIMIT 100;
Para buscar los 100 vectores más cercanos a un embedding que genera una expresión SQL, usa el siguiente patrón. En este ejemplo, la consulta busca los documentos que son más similares a la incorporación de UserId = 1 y DocId = 1:
GoogleSQL
WITH emb AS (
SELECT DocEmbedding AS value
FROM Documents
WHERE UserId = 1 AND DocId = 1
LIMIT 1
)
SELECT DocId
FROM Documents, emb
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
emb.value, DocEmbedding,
options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100
PostgreSQL
SELECT documents.doc_id
FROM
documents,
(
SELECT doc_embedding AS value
FROM documents
WHERE user_id = 1 AND doc_id = 1
LIMIT 1
) vector
WHERE documents.doc_embedding IS NOT NULL
ORDER BY spanner.APPROX_EUCLIDEAN_DISTANCE(documents.doc_embedding,
vector.value, options=>'{"num_leaves_to_search": 10}'::jsonb)
LIMIT 100
Si la columna de incorporación es anulable:
GoogleSQL
SELECT DocId
FROM Documents
WHERE NullableDocEmbedding IS NOT NULL AND WordCount > 1000
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
ARRAY<FLOAT32>[1.0, 2.0, 3.0], NullableDocEmbedding,
options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100
PostgreSQL
SELECT doc_id
FROM documents
WHERE nullable_doc_embedding IS NOT NULL AND word_count > 1000
ORDER BY spanner.approx_euclidean_distance(
ARRAY[1.0, 2.0, 3.0]::float4[], nullable_doc_embedding,
options=>jsonb'{"num_leaves_to_search": 10}'
)
LIMIT 100;
¿Qué sigue?
Obtén más información sobre los índices de vectores de Spanner .
Obtén más información sobre las funciones de distancia aproximada en GoogleSQL y PostgreSQL.
Obtén más información sobre las instrucciones de índice para GoogleSQL
VECTOR INDEXy PostgreSQLINDEX.Obtén más información sobre las prácticas recomendadas para los índices de vectores.
Prueba la sección Primeros pasos con la búsqueda de vectores de Spanner para obtener un ejemplo paso a paso del uso de ANN.