Crear un índice de ScaNN

En esta página se describe cómo usar las inserciones almacenadas para generar índices y consultar inserciones mediante el índice ScaNN con AlloyDB para PostgreSQL. Para obtener más información sobre cómo almacenar inserciones, consulta Almacenar inserciones de vectores.

AlloyDB alloydb_scann, una extensión de PostgreSQL desarrollada por Google que implementa un índice de vecinos más cercanos muy eficiente basado en el algoritmo ScaNN.

El índice ScaNN es un índice de cuantificación basado en árbol para la búsqueda aproximada de vecinos más cercanos. Ofrece un tiempo de creación de índices más corto y un menor uso de memoria en comparación con HNSW. Además, ofrece un QPS más rápido en comparación con HNSW en función de la carga de trabajo.

Antes de empezar

Antes de empezar a crear índices, debes completar los siguientes requisitos previos.

  • Los vectores de inserción se añaden a una tabla de tu base de datos de AlloyDB.

  • Se instalan la extensión vector basada en pgvector, ampliada por Google para AlloyDB, y la extensión alloydb_scann:

    CREATE EXTENSION IF NOT EXISTS alloydb_scann CASCADE;
    
  • Si quieres crear índices de ScaNN optimizados automáticamente, asegúrate de que la marca scann.enable_preview_features esté habilitada. Si no quieres habilitar las funciones de vista previa o si se trata de instancias de producción, puedes crear un índice de ScaNN con parámetros específicos.

Crear un índice de ScaNN ajustado automáticamente

Con la función de indexación automática, puede simplificar la creación de índices para crear automáticamente índices optimizados para el rendimiento de búsqueda o para equilibrar los tiempos de compilación de índices y el rendimiento de búsqueda.

Cuando usas el modo AUTO, solo tienes que especificar el nombre de la tabla y la columna de inserción, así como la función de distancia que quieras usar. Puede optimizar el índice para mejorar el rendimiento de la búsqueda o para encontrar un equilibrio entre los tiempos de compilación del índice y el rendimiento de la búsqueda.

También puedes usar el modo MANUAL para crear índices con un control granular sobre otros parámetros de ajuste de índices.

Crear un índice de ScaNN en modo AUTO

A continuación, se indican algunos aspectos que debes tener en cuenta antes de crear índices en el modo AUTO:

  • AlloyDB no puede crear un índice ScaNN para tablas con datos insuficientes.
  • No puedes definir parámetros de creación de índices, como num_leaves, cuando creas índices en el modo AUTO.
  • La función de mantenimiento automático está habilitada de forma predeterminada en todos los índices creados en el modo AUTO.

Para crear un índice en el modo AUTO, primero debes habilitar el feature flag scann.zero_knob_index_creation. Después de habilitar la marca, ejecuta el siguiente comando:

      CREATE INDEX INDEX_NAME ON TABLE \
      USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION) \
      WITH (mode=AUTO', optimization='OPTIMIZATION');

Haz los cambios siguientes:

  • INDEX_NAME: el nombre del índice que quieras crear (por ejemplo, my-scann-index). Los nombres de los índices se comparten en toda la base de datos. Verifica que cada nombre de índice sea único para cada tabla de tu base de datos.

  • TABLE: la tabla a la que se va a añadir el índice.

  • EMBEDDING_COLUMN: columna que almacena datos de vector.

  • DISTANCE_FUNCTION: la función de distancia que se va a usar con este índice. Elige una de estas opciones:

    • Distancia L2: l2

    • Producto escalar: dot_product

    • Distancia del coseno: cosine

  • OPTIMIZATION: se debe configurar como uno de los siguientes valores:

    • SEARCH_OPTIMIZED: para optimizar tanto la recuperación de la búsqueda de vectores como la latencia de la búsqueda de vectores a costa de un mayor tiempo de compilación del índice.
    • BALANCED: para crear un índice que equilibre el tiempo de compilación del índice y el rendimiento de la búsqueda.

Crear un índice ScaNN en modo MANUAL

Si has habilitado la marca scann.enable_preview_features y quieres tener un control granular sobre los parámetros de ajuste, puedes crear el índice en modo MANUAL.

Para crear un índice ScaNN en modo MANUAL, ejecuta el siguiente comando:

      CREATE INDEX INDEX_NAME ON TABLE \
      USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION) \
      WITH (mode='MANUAL, num_leaves=NUM_LEAVES_VALUE, [quantizer =QUANTIZER, max_num_levels=MAX_NUM_LEVELS]);

Haz los cambios siguientes:

  • INDEX_NAME: el nombre del índice que quieras crear (por ejemplo, my-scann-index). Los nombres de los índices se comparten en toda la base de datos. Verifica que cada nombre de índice sea único para cada tabla de tu base de datos.

  • TABLE: la tabla a la que se va a añadir el índice.

  • EMBEDDING_COLUMN: columna que almacena datos de vector.

  • DISTANCE_FUNCTION: la función de distancia que se va a usar con este índice. Elige una de estas opciones:

    • Distancia L2: l2

    • Producto escalar: dot_product

    • Distancia del coseno: cosine

  • NUM_LEAVES_VALUE: el número de particiones que se aplicarán a este índice. Puede ser cualquier valor entre 1 y 1048576.

  • QUANTIZER: el tipo de cuantificador que se va a usar. Estas son las opciones disponibles:

    • SQ8: ofrece un equilibrio entre el rendimiento de las consultas y la pérdida mínima de recuerdo, que suele ser inferior al 1-2%. Este es el valor predeterminado.
    • AH: ten en cuenta esta opción para mejorar el rendimiento de las consultas cuando el motor de columnas esté habilitado y los datos de índice y de tabla se hayan insertado en el motor de columnas, en función del tamaño configurado. Ten en cuenta que AH se comprime hasta 4 veces en comparación con SQ8. Para obtener más información, consulta Prácticas recomendadas para optimizar ScaNN.
    • FLAT: ofrece el mayor recuerdo, del 99% o más, a costa del rendimiento de la búsqueda.
  • MAX_NUM_LEVELS: número máximo de niveles del árbol de clústeres de k-means. El valor predeterminado es 1, que corresponde a la cuantización basada en un árbol de dos niveles, y 2, que corresponde a la cuantización basada en un árbol de tres niveles.

Puede añadir otros parámetros de creación de índices o de tiempo de ejecución de consultas para optimizar el índice. Para obtener más información, consulta Ajustar un índice de ScaNN.

Cambiar los modos de los índices

Si has creado un índice de ScaNN con el modo AUTO y quieres ajustarlo manualmente, debes cambiar el modo a MANUAL.

Para cambiar al modo MANUAL, sigue estos pasos:

  1. Actualiza el índice para definir el modo MANUAL:

    ALTER INDEX INDEX_NAME SET (mode = 'MANUAL', num_leaves = NUM_LEAVES_VALUE);
    

    Haz los cambios siguientes:

    • INDEX_NAME: el nombre del índice que quieras crear (por ejemplo, my-scann-index). Los nombres de los índices se comparten en toda la base de datos. Verifique que el nombre de cada índice sea único para cada tabla de su base de datos.

    • NUM_LEAVES_VALUE: el número de particiones que se aplicarán a este índice. Puede ser cualquier valor entre 1 y 1048576.

    Puede añadir otros parámetros de creación de índices o de tiempo de ejecución de consultas para optimizar el índice. Para obtener más información, consulta Ajustar un índice de ScaNN.

  2. Reconstruye el índice para aplicar los parámetros:

    REINDEX INDEX CONCURRENTLY INDEX_NAME;
    

Para cambiar al modo AUTO, sigue estos pasos:

  1. Actualiza el índice para definir el modo AUTO:

    ALTER INDEX INDEX_NAME SET (mode = 'AUTO');
    
  2. Reconstruye el índice para aplicar los parámetros:

    REINDEX INDEX CONCURRENTLY INDEX_NAME;
    

Crear un índice ScaNN con parámetros específicos

Si tu aplicación tiene requisitos específicos para los tiempos de recuperación y de compilación de índices, puedes crear el índice manualmente. Puedes crear un índice de árbol de dos o tres niveles en función de tu carga de trabajo. Para obtener más información sobre cómo ajustar los parámetros, consulta Ajustar un índice ScaNN.

Índice de árbol de dos niveles

Para aplicar un índice de árbol de dos niveles con el algoritmo ScaNN a una columna que contenga incrustaciones de vectores almacenadas, ejecuta la siguiente consulta DDL:

CREATE INDEX INDEX_NAME ON TABLE
  USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
  WITH (num_leaves=NUM_LEAVES_VALUE, quantizer =QUANTIZER);

Haz los cambios siguientes:

  • INDEX_NAME: el nombre del índice que quieras crear (por ejemplo, my-scann-index). Los nombres de los índices se comparten en toda la base de datos. Asegúrate de que cada nombre de índice sea único para cada tabla de tu base de datos.

  • TABLE: la tabla a la que se va a añadir el índice.

  • EMBEDDING_COLUMN: una columna que almacena vector datos.

  • DISTANCE_FUNCTION: la función de distancia que se va a usar con este índice. Elige una de estas opciones:

    • Distancia L2: l2

    • Producto escalar: dot_product

    • Distancia del coseno: cosine

  • NUM_LEAVES_VALUE: el número de particiones que se aplicarán a este índice. Puede ser cualquier valor entre 1 y 1048576. Para obtener más información sobre cómo decidir este valor, consulta Ajustar un índice de ScaNN.

  • QUANTIZER: el tipo de cuantificador que se va a usar. Estas son las opciones disponibles:

    • SQ8: ofrece un equilibrio entre el rendimiento de las consultas y la pérdida mínima de recuerdo, que suele ser inferior al 1-2%. Este es el valor predeterminado.
    • AH: ten en cuenta esta opción para mejorar el rendimiento de las consultas cuando el motor de columnas esté habilitado y los datos de índice y de tabla se hayan insertado en el motor de columnas, en función del tamaño configurado. Ten en cuenta que AH se comprime hasta 4 veces en comparación con SQ8. Para obtener más información, consulta Prácticas recomendadas para optimizar ScaNN.
    • FLAT: ofrece el mayor recuerdo, del 99% o más, a costa del rendimiento de la búsqueda.

Índice de árbol de tres niveles

Para crear un índice de árbol de tres niveles con el algoritmo ScaNN en una columna que contenga inserciones de vectores almacenadas, ejecuta la siguiente consulta DDL:

CREATE INDEX INDEX_NAME ON TABLE
  USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
  WITH (num_leaves=NUM_LEAVES_VALUE, max_num_levels = 2);

Una vez que hayas creado el índice, podrás ejecutar consultas de búsqueda de vecinos más cercanos que utilicen el índice siguiendo las instrucciones de Hacer una consulta de vecinos más cercanos con un texto determinado.

Los parámetros de índice deben configurarse para lograr un equilibrio entre las consultas por segundo y la recuperación. Para obtener más información sobre cómo optimizar el índice ScaNN, consulta Optimizar un índice ScaNN.

Para crear este índice en una columna de inserciones que use el tipo de datos real[] en lugar de vector, convierte la columna al tipo de datos vector:

CREATE INDEX INDEX_NAME ON TABLE
  USING scann (CAST(EMBEDDING_COLUMN AS vector(DIMENSIONS)) DISTANCE_FUNCTION)
  WITH (num_leaves=NUM_LEAVES_VALUE, max_num_levels = MAX_NUM_LEVELS);

Sustituye DIMENSIONS por el ancho dimensional de la columna de inserción. Para obtener más información sobre cómo encontrar las dimensiones, consulta la función vector_dims en Funciones de vector.

Para ofrecer una experiencia de búsqueda coherente, habilita el mantenimiento automático al crear un índice de ScaNN. Para obtener más información, consulta Mantener índices vectoriales. Esta función está disponible en versión preliminar.

Para ver el progreso de la indexación, usa la vista pg_stat_progress_create_index:

SELECT * FROM pg_stat_progress_create_index;

La columna phase muestra el estado actual de la creación del índice. Una vez completada la fase de creación del índice, la fila del índice no se muestra.

Para ajustar el índice de forma que se consiga un equilibrio entre la media de la recuperación y las consultas por segundo, consulta Ajustar un índice ScaNN.

Crear índices en paralelo

Para crear el índice más rápido, AlloyDB puede generar automáticamente varios procesos paralelos, en función de tu conjunto de datos y del tipo de índice que elijas.

La creación de índices paralela se suele activar si creas un índice ScaNN de tres niveles o si tu conjunto de datos supera los 100 millones de filas.

Aunque AlloyDB optimiza automáticamente el número de trabajadores paralelos, puedes ajustar los trabajadores paralelos mediante los parámetros de planificación de consultas de PostgreSQL max_parallel_maintenance_workers, max_parallel_workers y min_parallel_table_scan_size.

Ejecutar una consulta

Una vez que hayas almacenado e indexado las inserciones en tu base de datos, podrás empezar a consultar tus datos. No puedes ejecutar consultas de búsqueda masivas con la extensión alloydb_scann.

Para encontrar los vecinos semánticos más cercanos de un vector de embedding, puedes ejecutar la siguiente consulta de ejemplo, en la que se define la misma función de distancia que se usó durante la creación del índice.

  SELECT * FROM TABLE
    ORDER BY EMBEDDING_COLUMN DISTANCE_FUNCTION_QUERY ['EMBEDDING']
    LIMIT ROW_COUNT

Haz los cambios siguientes:

  • TABLE: la tabla que contiene la inserción con la que se va a comparar el texto.

  • INDEX_NAME: el nombre del índice que quieras usar. Por ejemplo, my-scann-index.

  • EMBEDDING_COLUMN: la columna que contiene las inserciones almacenadas.

  • DISTANCE_FUNCTION_QUERY: la función de distancia que se va a usar con esta consulta. Elige una de las siguientes opciones en función de la función de distancia utilizada al crear el índice:

    • Distancia L2: <->

    • Producto interior: <#>

    • Distancia del coseno: <=>

  • EMBEDDING: el vector de inserción del que quieres encontrar los vecinos semánticos almacenados más cercanos.

  • ROW_COUNT: número de filas que se van a devolver.

    Especifica 1 si solo quieres la mejor coincidencia.

También puedes usar la función embedding() para traducir el texto a un vector. Como embedding() devuelve una matriz real, debes convertir explícitamente la llamada embedding() a vector antes de aplicarla a uno de los operadores de vecinos más cercanos (por ejemplo, <-> para la distancia L2). Estos operadores pueden usar el índice ScaNN para encontrar las filas de la base de datos con las inserciones semánticamente más similares.

Siguientes pasos