En esta página, se describe cómo crear un índice vectorial y consultar incorporaciones de vectores con la distancia aproximada del coseno, la distancia euclidiana aproximada y las funciones de vectores de producto punto aproximados. Puedes usar estas para encontrar los vecinos más cercanos (ANN) en Spanner. Cuando un conjunto de datos es pequeño, puedes usar k-vecinos más cercanos (KNN) para encontrar los vectores exactos de k-vecinos más cercanos. Sin embargo, a medida que tu conjunto de datos crece, la latencia y el costo de una búsqueda de KNN también aumentan. Puedes usar ANN para encontrar los vecinos aproximados más cercanos con una latencia y un costo significativamente reducidos.
Vecinos k-más cercanos aproximados
En una búsqueda de ANN, los vectores que muestra k no son el verdadero k superior más cercano vecinos. En ocasiones, algunos vectores que no se encuentran entre los k-más cercanos vecinos. Esto se conoce como pérdida de recuperación. ¿Cuánta pérdida de recuperación es aceptable para ti depende del caso de uso, pero, en la mayoría de los casos, perder a cambio de un mejor rendimiento de la base de datos es un compensación.
Para obtener más detalles sobre las funciones de distancia aproximada de Spanner, consulta lo siguiente:
APPROX_COSINE_DISTANCE
en GoogleSQLAPPROX_EUCLIDEAN_DISTANCE
en GoogleSQLAPPROX_DOT_PRODUCT
en GoogleSQL
Índice vectorial
Spanner acelera las búsquedas de vectores ANN a través de una interfaz índice vectorial. Este índice aprovecha el vecino más cercano escalable (ScaNN) de Google Research, un algoritmo de vecino más cercano altamente eficiente.
El índice vectorial usa una estructura basada en árboles para particionar datos y facilitar búsquedas más rápidas. Spanner ofrece configuraciones de árbol de dos y tres niveles:
- Configuración de árbol de dos niveles: Los nodos hoja (
num_leaves
) contienen grupos de vectores estrechamente relacionados junto con su centroide correspondiente. El nivel raíz consiste en los centroides de todos los nodos hoja. - Configuración de árbol de tres niveles: un concepto similar al de un árbol de dos niveles,
introduciendo una capa de rama adicional (
num_branches
) a partir de la cual un nodo de hoja los centroides se particionan aún más para formar el nivel raíz (num_leaves
).
Además, debes crear tu índice vectorial con una métrica de distancia específica.
Para elegir la métrica de distancia más adecuada para tu caso de uso, configura distance_type
en una de las siguientes opciones: COSINE
, DOT_PRODUCT
o EUCLIDEAN
.
Para obtener más información, consulta las sentencias VECTOR INDEX
.
Limitaciones
El índice vectorial de Spanner tiene las siguientes limitaciones:
ALTER VECTOR INDEX
no es compatible.
Crea un índice vectorial
Para optimizar el índice vectorial a fin de lograr una recuperación y un rendimiento óptimos, recomendamos que crees tu índice vectorial después de que la mayoría de las filas con incorporaciones estén se escribe en tu base de datos. También es posible que debas hacer ajustes vuelve a compilar el índice vectorial después de insertar nuevos datos. Para obtener más información, consulta Cómo volver a compilar el índice vectorial.
Para crear un índice vectorial con un árbol de dos niveles y 1,000 nodos de hoja en una
tabla Documents
con una columna de incorporación DocEmbedding
usando la distancia de coseno, haz lo siguiente:
CREATE VECTOR INDEX DocEmbeddingIndex
ON Documents(DocEmbedding)
OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);
Para crear un índice vectorial con un árbol de tres niveles y 1000000 nodos de hoja, haz lo siguiente:
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);
Si tu columna de incorporación admite valores nulos, debes declararla con una cláusula 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);
Consulta embeddings de vectores
Para consultar un índice vectorial, utiliza una de las tres funciones de distancia aproximada:
APPROX_COSINE_DISTANCE
APPROX_EUCLIDEAN_DISTANCE
APPROX_DOT_PRODUCT
Las restricciones para el uso de las funciones de distancia aproximada incluyen la lo siguiente:
- Debes indicar una sugerencia de consulta para usar el índice vectorial.
- Debes usar una expresión constante como argumento de la función de distancia (por ejemplo, un parámetro o un literal).
- La consulta o subconsulta en la que se usa la función de distancia aproximada debe tener una forma específica: la función de distancia debe ser la única clave
ORDER BY
, y se debe especificar un límite.
Para obtener una lista detallada de las limitaciones, consulta el página de referencia de la función de distancia aproximada.
Ejemplo
Para buscar los 100 vectores más cercanos a [1.0, 2.0, 3.0]
, haz lo siguiente:
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
Si la columna de incorporación es anulable:
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
Prácticas recomendadas
Sigue estas prácticas recomendadas para optimizar los índices vectoriales y mejorar las consultas resultados.
Ajusta las opciones de búsqueda vectorial
El valor de búsqueda de vectores más óptimo depende del caso de uso, del conjunto de datos de vectores y de los vectores de consulta. Quizás debas realizar un ajuste iterativo para a encontrar los mejores valores para tu carga de trabajo específica.
Estos son algunos lineamientos útiles que debes seguir cuando elijas valores adecuados:
tree_depth
(nivel de árbol): Si la tabla a la que se le indexa tiene menos de 10 millones de filas, usa untree_depth
de2
. De lo contrario, unatree_depth
de3
. admite tablas de hasta 10,000 millones de filas.num_leaves
: Usa la raíz cuadrada de la cantidad de filas del conjunto de datos. Un valor más alto puede aumentar el tiempo de compilación del índice vectorial. Evita configurarnum_leaves
mayor quetable_row_count/1000
, ya que esto da como resultado hojas demasiado pequeñas y un rendimiento deficiente.num_leaves_to_search
: Esta opción especifica cuántos nodos de hoja del índice. los usuarios. Aumentarnum_leaves_to_search
mejora la recuperación, pero también aumenta la latencia y el costo. Recomendamos usar un número que sea el 1% de la cantidad total de hojas definidas en la sentenciaCREATE VECTOR INDEX
como el valor paranum_leaves_to_search
. Si usas una cláusula de filtro, aumenta este valor para ampliar la búsqueda.
Si se logra una recuperación aceptable, pero el costo de la consulta es demasiado alto, lo que genera una QPS máxima baja, intenta aumentar num_leaves
siguiendo estos pasos:
- Establece
num_leaves
en algún múltiplo de k de su valor original (por ejemplo,2 * sqrt(table_row_count)
). - Establece
num_leaves_to_search
como el mismo múltiplo k de su valor original. - Experimenta con la reducción de
num_leaves_to_search
para mejorar el costo y las QPS y, al mismo tiempo, mantener la recuperación.
Mejora la recuperación
Existen varias posibilidades de que empeore la recuperación, incluidas las siguientes:
num_leaves_to_search
es demasiado pequeño: Es posible que te resulte más difícil encontrar los vecinos más cercanos para algunos vectores de consulta, por lo que aumentarnum_leaves_to_search
para buscar más hojas puede ayudar a mejorar la recuperación. Recientes podrían haber cambiado para contener más de estos vectores desafiantes.Se debe volver a compilar el índice vectorial: La estructura de árbol del índice vectorial se optimiza para el conjunto de datos en el momento de la creación y es estática a partir de ese momento. Por lo tanto, si se agregan vectores muy diferentes después de crear el índice vectorial inicial, la estructura del árbol podría ser subóptima, lo que generaría una recuperación más deficiente.
Vuelve a compilar el índice vectorial
Para volver a compilar tu índice vectorial sin tiempo de inactividad, haz lo siguiente:
- Crea un índice vectorial nuevo en la misma columna de incorporación que el índice vectorial
actual y actualiza los parámetros (por ejemplo,
OPTIONS
) según corresponda. - Cuando se complete la creación del índice, cambia la sugerencia
FORCE_INDEX
. para apuntar al índice nuevo para actualizar la búsqueda vectorial. Esto garantiza que la consulta usa el nuevo índice vectorial. (Es posible que también debas volver a sintonizarnum_leaves_to_search
en tu nueva consulta). - Descarta el índice vectorial desactualizado.
¿Qué sigue?
Obtén más información sobre las funciones
APPROXIMATE_COSINE_DISTANCE()
,APPROXIMATE_EUCLIDEAN_DISTANCE()
yAPPROXIMATE_DOT_PRODUCT()
de GoogleSQL.Obtén más información sobre las instrucciones
VECTOR INDEX
de GoogleSQL.