Os índices Scalable Nearest Neighbors (ScaNN) no AlloyDB para PostgreSQL permitem acelerar as pesquisas vetoriais de vizinho mais próximo aproximado em embeddings armazenados.
O índice ScaNN é um índice de quantização baseado em árvore criado pelo Google para pesquisa de vizinho mais próximo aproximado. Ele oferece um tempo de criação de índice menor e um consumo de memória menor em comparação com o HNSW. Além disso, ele oferece QPS mais rápido em comparação com o HNSW, com base na carga de trabalho.
Antes de começar
Antes de começar a criar índices, você precisa atender aos seguintes pré-requisitos.
Os vetores de embedding são adicionados a uma tabela no banco de dados do AlloyDB.
Se você tentar gerar um índice ScaNN em uma tabela vazia ou particionada, poderá encontrar alguns problemas. Para mais informações sobre os erros gerados, consulte Resolver problemas de erros de índice do ScaNN. Para criar um índice em uma tabela vazia ou pequena, consulte Criação de índice adiada para tabelas vazias ou quase vazias.
As extensões
vectorealloydb_scannestão instaladas:CREATE EXTENSION IF NOT EXISTS alloydb_scann CASCADE;A instalação da extensão
alloydb_scannverifica automaticamente se a extensãovectorestá instalada e a instala se não estiver. Não é necessário instalar ovectormanualmente.Se você quiser criar um índice ScaNN de quatro níveis, primeiro ative o recurso de pré-lançamento na instância do AlloyDB. Para ativar o recurso de pré-lançamento, escolha um dos dois métodos a seguir:
Ative a flag de banco de dados
scann.enable_preview_features.Para mais informações sobre como configurar flags de banco de dados, consulte Configurar flags de banco de dados.
Defina a flag de banco de dados
scann.max_allowed_num_levelscomo3no nível da sessão ou da instância. Para definir a flag no nível da sessão, execute o seguinte comando:SET scann.max_allowed_num_levels = 3;Para definir a flag no nível da instância, execute
gcloud alloydb alloydb instances updateusando o campo--database-flags.
Criar um índice ajustado automaticamente
Os índices ScaNN ajustados automaticamente simplificam a criação de índices, permitindo que o AlloyDB gerencie e ajuste a estrutura do índice. Se você precisar de controle granular sobre o ajuste de índice, crie um índice ScaNN ajustado manualmente.
Os índices ajustados automaticamente podem ser otimizados de duas maneiras:
- (Padrão) Recall e latência da pesquisa vetorial ao custo do tempo de build do índice
- Equilibrar o tempo de build do índice e a performance da pesquisa
Para criar um índice ScaNN ajustado automaticamente, execute o comando a seguir.
CREATE INDEX INDEX_NAME ON TABLE
USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
Substitua:
INDEX_NAME: nome do índice que você quer criar. Por exemplo,my_scann_index. Os nomes de índice são compartilhados em todo o banco de dados. Verifique se cada nome de índice é exclusivo para cada tabela no banco de dados.TABLE: tabela em que o índice será adicionado.EMBEDDING_COLUMN: coluna que armazena dados devector.DISTANCE_FUNCTION: função de distância a ser usada com esse índice. Escolha uma destas opções:Distância de L2:
l2Produto escalar:
dot_productDistância do cosseno:
cosine
Esse comando cria um índice ScaNN otimizado para desempenho de pesquisa e realiza a manutenção automática do índice. Se você quiser mudar uma dessas configurações, execute o seguinte comando:
CREATE INDEX INDEX_NAME ON TABLE
USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
WITH (MODE='AUTO',
OPTIMIZATION='OPTIMIZATION',
auto_maintenance='AUTO_MAINTENANCE')
Substitua:
INDEX_NAME: nome do índice que você quer criar. Por exemplo,my_scann_index. Os nomes de índice são compartilhados em todo o banco de dados. Verifique se cada nome de índice é exclusivo para cada tabela no banco de dados.TABLE: tabela em que o índice será adicionado.EMBEDDING_COLUMN: coluna que armazena dados devector.DISTANCE_FUNCTION: função de distância a ser usada com esse índice. Escolha uma destas opções:Distância de L2:
l2Produto escalar:
dot_productDistância do cosseno:
cosine
(Opcional)
OPTIMIZATION: defina como um dos seguintes:(Padrão)
SEARCH_OPTIMIZED: otimiza o recall e a latência da pesquisa vetorial, mas aumenta o tempo de criação do índice.BALANCED: equilibra o tempo de criação do índice e o desempenho da pesquisa.
Se
OPTIMIZATIONestiver definido,MODE='AUTO'também precisará ser incluído.(Opcional)
AUTO_MAINTENANCE: controla se a manutenção automática do índice está ativada ou desativada. Para mais informações sobre manutenção automática, consulte Manter índices vetoriais.(Padrão)
ON: o AlloyDB realiza a manutenção automática do índice.OFF: o AlloyDB não realiza manutenção automática no índice.
Criar um índice ajustado manualmente
Se o aplicativo tiver requisitos específicos para tempos de recall e de build de índice, será possível criar e ajustar manualmente o índice do ScaNN.
Para criar manualmente um índice ScaNN para uma coluna que contém embeddings de vetor armazenados, consulte os comandos a seguir.
Índice de árvore de dois níveis
CREATE INDEX INDEX_NAME ON TABLE USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION) WITH (mode='MANUAL', num_leaves=NUM_LEAVES_VALUE, quantizer=QUANTIZER, auto_maintenance=AUTO_MAINTENANCE);
-
INDEX_NAME: nome do índice que você quer criar. Por exemplo,my_scann_index. Os nomes de índice são compartilhados em todo o banco de dados. Verifique se cada nome de índice é exclusivo para cada tabela no banco de dados. -
TABLE: tabela em que o índice será adicionado. -
EMBEDDING_COLUMN: coluna que armazena dados de "vetor". -
DISTANCE_FUNCTION: função de distância a ser usada com esse índice. Escolha uma das opções a seguir:- Distância de L2:
l2 - Produto escalar:
dot_product - Distância do cosseno:
cosine
- Distância de L2:
-
NUM_LEAVES_VALUE: número de partições a serem aplicadas a esse índice. Defina como qualquer valor entre 1 e 30 milhões. Para mais informações sobre como escolher esse valor, consulte Ajustar um índiceScaNN. -
QUANTIZER: tipo de quantizador a ser usado. O índice ScaNN pode ser carregado no mecanismo colunar para acelerar ainda mais a busca vetorial. Escolha uma das opções a seguir:-
(Padrão)
SQ8: oferece um equilíbrio entre o desempenho da consulta e a perda mínima de recall. Normalmente, isso é menos de 1 a 2%. -
Prévia
AH: o hash assimétrico (AH) é até quatro vezes mais compactado em comparação comSQ8. Para um desempenho potencialmente melhor da consulta quando o mecanismo colunar está ativado e os dados de índice e tabela são preenchidos no mecanismo colunar, considere isso para um desempenho potencialmente melhor da consulta. Para mais informações, consulte Práticas recomendadas para ajustar o ScaNN. -
FLAT: oferece o maior recall, 99% ou mais, ao custo do desempenho da pesquisa.
-
(Padrão)
-
(Opcional)
AUTO_MAINTENANCE: controla se a manutenção automática no índice está ativada ou desativada. Para mais informações sobre manutenção automática, consulte Manter índices vetoriais.-
(Padrão)
ON: o AlloyDB realiza a manutenção automática no índice. -
OFF: o AlloyDB não realiza manutenção automática no índice.
-
(Padrão)
Índice de árvore de três níveis
CREATE INDEX INDEX_NAME ON TABLE USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION) WITH (mode='MANUAL', num_leaves=NUM_LEAVES_VALUE, quantizer=QUANTIZER, auto_maintenance=AUTO_MAINTENANCE, max_num_levels = 2);
-
INDEX_NAME: nome do índice que você quer criar. Por exemplo,my_scann_index. Os nomes de índice são compartilhados em todo o banco de dados. Verifique se cada nome de índice é exclusivo para cada tabela no banco de dados. -
TABLE: tabela em que o índice será adicionado. -
EMBEDDING_COLUMN: coluna que armazena dados de "vetor". -
DISTANCE_FUNCTION: função de distância a ser usada com esse índice. Escolha uma das opções a seguir:- Distância de L2:
l2 - Produto escalar:
dot_product - Distância do cosseno:
cosine
- Distância de L2:
-
NUM_LEAVES_VALUE: número de partições a serem aplicadas a esse índice. Defina como qualquer valor entre 1 e 30 milhões. Para mais informações sobre como escolher esse valor, consulte Ajustar um índiceScaNN. -
QUANTIZER: tipo de quantizador a ser usado. O índice ScaNN pode ser carregado no mecanismo colunar para acelerar ainda mais a pesquisa vetorial. Escolha uma das opções a seguir:-
(Padrão)
SQ8: oferece um equilíbrio entre o desempenho da consulta e a perda mínima de recall. Isso geralmente é inferior a 1% a 2%. -
Pré-lançamento
AH: o hash assimétrico (AH) é até 4 vezes mais compactado em comparação comSQ8. Para melhorar o desempenho da consulta quando o mecanismo colunar estiver ativado e os dados do índice e da tabela forem preenchidos no mecanismo colunar, considere isso para melhorar o desempenho da consulta. Para mais informações, consulte Práticas recomendadas para ajustar o ScaNN. -
FLAT: oferece o maior recall, 99% ou mais, ao custo do desempenho da pesquisa.
-
(Padrão)
-
(Opcional)
AUTO_MAINTENANCE: controla se a manutenção automática do índice está ativada ou desativada. Para mais informações sobre manutenção automática, consulte Manter índices vetoriais.-
(Padrão)
ON: o AlloyDB realiza a manutenção automática no índice. -
OFF: o AlloyDB não realiza manutenção automática no índice.
-
(Padrão)
-
max_num_levels = 2: o número máximo de níveis de centroide da árvore de clustering k-means. Defina esse parâmetro como2para criar um índice de três níveis.
Índice de árvore de quatro níveis
CREATE INDEX INDEX_NAME ON TABLE USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION) WITH (mode='MANUAL', num_leaves=NUM_LEAVES_VALUE, quantizer=QUANTIZER, auto_maintenance=AUTO_MAINTENANCE, max_num_levels = 3);
-
INDEX_NAME: nome do índice que você quer criar. Por exemplo,my_scann_index. Os nomes de índice são compartilhados em todo o banco de dados. Verifique se cada nome de índice é exclusivo para cada tabela no banco de dados. -
TABLE: tabela em que o índice será adicionado. -
EMBEDDING_COLUMN: coluna que armazena dados de "vetor". -
DISTANCE_FUNCTION: função de distância a ser usada com esse índice. Escolha uma das opções a seguir:- Distância de L2:
l2 - Produto escalar:
dot_product - Distância do cosseno:
cosine
- Distância de L2:
-
NUM_LEAVES_VALUE: número de partições a serem aplicadas a esse índice. Definido como qualquer valor entre 1 e 30 milhões. Para mais informações sobre como escolher esse valor, consulte Ajustar um índiceScaNN. -
QUANTIZER: tipo de quantizador a ser usado. O índice ScaNN pode ser carregado no mecanismo colunar para acelerar ainda mais a pesquisa vetorial. Escolha uma das opções a seguir:-
(Padrão)
SQ8: oferece um equilíbrio entre o desempenho da consulta e a perda mínima de recall. Normalmente, isso é menos de 1 a 2%. -
Prévia
AH: o hash assimétrico (AH) é até quatro vezes mais compactado em comparação comSQ8. Para um desempenho potencialmente melhor da consulta quando o mecanismo colunar está ativado e os dados de índice e tabela são preenchidos no mecanismo colunar, considere isso para um desempenho potencialmente melhor da consulta. Para mais informações, consulte Práticas recomendadas para ajustar o ScaNN. -
FLAT: oferece o maior recall, 99% ou mais, ao custo do desempenho da pesquisa.
-
(Padrão)
-
(Opcional)
AUTO_MAINTENANCE: controla se a manutenção automática do índice está ativada ou desativada. Para mais informações sobre a manutenção automática, consulte Manter índices vetoriais.-
(Padrão)
ON: o AlloyDB realiza a manutenção automática do índice. -
OFF: o AlloyDB não realiza manutenção automática no índice.
-
(Padrão)
-
max_num_levels = 3: o número máximo de níveis de centroide da árvore de clustering k-means. Defina esse parâmetro como3para criar um índice de quatro níveis.
Converter um índice ajustado manualmente em um índice ajustado automaticamente
Para converter um índice ajustado manualmente em um ajustado automaticamente, siga estas etapas:
Redefina todos os parâmetros de consulta definidos para o índice ajustado manualmente.
ALTER INDEX INDEX_NAME RESET (PARAMETER_NAME);Substitua as seguintes variáveis:
INDEX_NAME: nome do índice que você quer converter. Por exemplo,my_scann_index. Os nomes de índice são compartilhados em todo o banco de dados. Verifique se cada nome de índice é exclusivo para cada tabela no banco de dados.PARAMETER_NAME: lista separada por vírgulas que contém os nomes dos parâmetros de consulta que você quer redefinir. Por exemplo,num_leaves, quantization.É necessário redefinir todos os outros parâmetros de consulta antes de redefinir
num_leaves.
Reindexe o índice ajustado manualmente para convertê-lo em um índice ajustado automaticamente.
REINDEX INDEX CONCURRENTLY INDEX_NAME;
Criar um índice ScaNN para tipos de dados real[]
Para criar um índice para uma coluna de embedding que usa o tipo de dados real[]
em vez de vector, converta a coluna no tipo de dados vector:
CREATE INDEX INDEX_NAME ON TABLE
USING scann (CAST(EMBEDDING_COLUMN AS vector(DIMENSIONS)) DISTANCE_FUNCTION)
Substitua:
INDEX_NAME: nome do índice que você quer criar. Por exemplo,my_scann_index. Os nomes de índice são compartilhados em todo o banco de dados. Verifique se cada nome de índice é exclusivo para cada tabela no banco de dados.TABLE: tabela em que o índice será adicionado.DIMENSIONS: o número de dimensões que o modelo aceita.EMBEDDING_COLUMN: coluna que armazena dados devector.DISTANCE_FUNCTION: função de distância a ser usada com esse índice. Escolha uma destas opções:Distância de L2:
l2Produto escalar:
dot_productDistância do cosseno:
cosine
Ver o progresso da indexação
Para conferir o progresso da indexação, use a visualização pg_stat_progress_create_index:
SELECT * FROM pg_stat_progress_create_index;
A coluna phase mostra o estado atual da criação do índice. Depois que a fase de criação do índice for concluída, a linha do índice não vai ficar visível.
Criar um índice adiado para tabelas vazias ou com linhas insuficientes
Por padrão, não é possível criar um índice ScaNN em uma tabela vazia ou que tenha menos
linhas do que o valor da opção de índice num_leaves.
Para contornar essa limitação, ative a criação de índice adiada para permitir que o AlloyDB adie a criação de índice até que o número de linhas na tabela atinja o limite definido por num_leaves. Depois que o limite é
atingido, o AlloyDB inicia a criação do índice em segundo plano.
Essa operação adiada é um processo não bloqueador, permitindo que outras operações de banco de dados, como leituras e gravações, continuem sem interrupção. Como a reconstrução do índice acontece em segundo plano, a criação de índice adiada é adequada quando as tabelas ingerem linhas de dados em pequenos lotes. A recriação do índice é acionada automaticamente quando o número de linhas atinge o limite.
No entanto, se você planeja inserir um grande número de linhas na tabela em uma única transação, recomendamos dividir a transação em várias ou gerar um índice ScaNN sem ativar a criação adiada de índice.
Ativar a criação de índice adiada
Para ativar a criação de índice adiada, siga estas etapas:
Verifique se a flag
scann.enable_index_maintenancee uma das seguintes flags estão ativadas:scann.enable_preview_features: essa flag também ativa outros recursos em fase de pré-lançamento.scann.enable_index_with_insufficient_data: essa flag ativa explicitamente apenas o recurso de criação de índice adiada.
Para configurar o uso, use a CLI
gcloud:Para ativar a criação de índice adiada com outros recursos em fase de pré-lançamento:
gcloud alloydb instances update INSTANCE_ID \ --database-flags scann.enable_index_maintenance=on \ --database-flags scann.enable_preview_features=on \ --region=REGION_ID \ --cluster=CLUSTER_ID \ --project=PROJECT_IDPara ativar explicitamente a criação de índice adiada sem ativar outros recursos em fase de pré-lançamento:
gcloud alloydb instances update INSTANCE_ID \ --database-flags scann.enable_index_maintenance=on \ --database-flags scann.enable_index_with_insufficient_data=on \ --region=REGION_ID \ --cluster=CLUSTER_ID \ --project=PROJECT_ID
Substitua:
INSTANCE_ID: o ID da instância.REGION_ID: a região em que a instância está localizada, por exemplo,us-central1.CLUSTER_ID: o ID do cluster em que a instância está localizada.PROJECT_ID: o ID do projeto em que o cluster está localizado.
Crie um índice ScaNN:
Para criar um índice com ajuste automático, especifique explicitamente
WITH (MODE='AUTO')na instruçãoCREATE INDEX:CREATE INDEX INDEX_NAME ON TABLE USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION) WITH (MODE='AUTO')Para mais informações sobre os parâmetros, consulte Criar um índice ajustado automaticamente.
Para criar um índice ajustado manualmente, verifique se o parâmetro
auto_maintenanceestá definido comoon. Para mais informações, consulte Criar um índice ajustado manualmente.
Limitações
- O processo em segundo plano de criação automática de índices usa valores de flag no nível do banco de dados. Mesmo que você defina flags no nível da sessão usando o comando
SET LOCAL, o processo considera o valor da flag definido no nível do banco de dados. - Se você planeja inserir em massa uma grande quantidade de dados em uma tabela vazia em uma única transação, recomendamos executar a transação de inserção única e, em seguida, criar um índice ScaNN.
Forçar a criação de índices em tabelas vazias ou pequenas
O AlloyDB usa validações para impedir a criação de um índice ScaNN em uma tabela vazia ou com poucas linhas pelos seguintes motivos:
O índice do ScaNN é treinado com dados insuficientes. Isso pode resultar em um recall ruim para pesquisas de similaridade de vetor.
A performance de gravação no banco de dados pode ser prejudicada.
Recomendamos que você atrase a criação de índices em desempenho abaixo do ideal.
No entanto, em alguns cenários de desenvolvimento ou teste, talvez seja necessário criar um índice em uma tabela vazia ou pequena. Nesses casos, é possível aplicar a criação de
índices. Para forçar a criação de índices, é preciso ter privilégios de SUPERUSER.
Para forçar a criação do índice, siga estas etapas:
Defina o parâmetro
scann.allow_blocked_operationsno nível da sessão comotrueno banco de dados:SET scann.allow_blocked_operations = true;Se o usuário que você está usando para executar essas consultas não tiver privilégios
SUPERUSER, atribua-os:CREATE USER USERNAME WITH SUPERUSER PASSWORD PASSWORD;Substitua as seguintes variáveis:
USERNAME: nome do usuário a quem você quer conceder privilégios deSUPERUSER.PASSWORD: senha do usuário.
Criar índices em paralelo
Para criar o índice mais rapidamente, o AlloyDB pode gerar automaticamente vários workers paralelos, dependendo do conjunto de dados e do tipo de índice escolhido. Isso geralmente acontece ao criar um índice ScaNN de três ou quatro níveis ou se o conjunto de dados exceder 100 milhões de linhas.
Embora o AlloyDB otimize automaticamente o número de workers paralelos, é possível ajustar esses workers usando os seguintes parâmetros de planejamento de consultas do PostgreSQL:
Para evitar problemas de falta de memória ao criar o índice ScaNN, verifique se as flags de banco de dados maintenance_work_mem e shared_buffers estão definidas com um valor menor que a memória total da máquina.
Executar uma consulta
Depois de armazenar e indexar os embeddings no banco de dados, você pode começar
a consultar os dados. Não é possível executar consultas de pesquisa em massa usando a extensão alloydb_scann.
Para encontrar os vizinhos semânticos mais próximos de uma string de texto, use a
função google_ml.embedding() para converter o texto em um vetor.
Como google_ml.embedding() retorna uma matriz real, é necessário transmitir explicitamente
a chamada de função para vector antes de aplicá-la a um dos operadores de vizinho mais próximo, por exemplo, <-> para a distância L2. Esses operadores podem usar o índice ScaNN para encontrar as linhas do banco de dados com os embeddings mais semanticamente semelhantes.
SELECT * FROM TABLE
ORDER BY EMBEDDING_COLUMN DISTANCE_FUNCTION_QUERY
google_ml.embedding(
model_id => 'MODEL_ID',
content => 'CONTENT')::vector
LIMIT ROW_COUNT
Substitua as seguintes variáveis:
TABLE: tabela que contém o embedding com o qual você vai comparar o texto.EMBEDDING_COLUMN: coluna que contém os embeddings armazenados.DISTANCE_FUNCTION_QUERY: função de distância a ser usada com essa consulta. Escolha a consulta equivalente à função de distância ao criar o índice:Distância de L2:
<->Produto interno:
<#>Distância do cosseno:
<=>
MODEL_ID: ID do modelo de embedding registrado que você quer usar.CONTENT: a string de texto que você quer traduzir em um embedding e pesquisar.ROW_COUNT: número de linhas a serem retornadas. Por exemplo, especifique1se você quiser apenas a melhor correspondência.
A seguir
- Fazer pesquisas de similaridade vetorial
- Ajustar o desempenho da consulta vetorial
- Métricas de índice vetorial
- Aprenda a criar um assistente de compras inteligente com o AlloyDB, o pgvector e o gerenciamento de endpoints de modelo.