Os índices de vizinhos mais próximos escalonáveis (ScaNN, na sigla em inglês) no AlloyDB para PostgreSQL permitem acelerar as pesquisas vetoriais de vizinhos mais próximos aproximados 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 concluir os 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 í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 manualmente ovectorseparadamente.
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 criação do índice
- Equilibrar o tempo de criação do índice e o desempenho 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 manutenção automática de í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
OPTIMIZATIONfor 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 no í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 criação 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 100 milhões para o PostgreSQL versão 17 e mais recentes, e entre 1 e 30 milhões para o PostgreSQL versão 16 e anteriores. Para mais informações, 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. 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 no índice está ativada ou desativada. Para mais informações sobre manutenção automática, consulte Manter índices vetoriais.-
ON: o AlloyDB realiza a manutenção automática no índice. -
(Padrão)
OFF: o AlloyDB não realiza manutenção automática no índice.
-
Í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 100 milhões para o PostgreSQL versão 17 e mais recentes, e entre 1 e 30 milhões para o PostgreSQL versão 16 e anteriores. Para mais informações, 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. 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 no índice está ativada ou desativada. Para mais informações sobre manutenção automática, consulte Manter índices vetoriais.-
ON: o AlloyDB realiza a manutenção automática no índice. -
(Padrão)
OFF: o AlloyDB não realiza manutenção automática no índice.
-
-
max_num_levels = 2: o número máximo de níveis de centroide da árvore de clustering de 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. Defina como qualquer valor entre 1 e 100 milhões para o PostgreSQL versão 17 e mais recentes, e entre 1 e 30 milhões para o PostgreSQL versão 16 e anteriores. Para mais informações, 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. 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 no índice está ativada ou desativada. Para mais informações sobre manutenção automática, consulte Manter índices vetoriais.-
ON: o AlloyDB realiza a manutenção automática no índice. -
(Padrão)
OFF: o AlloyDB não realiza manutenção automática no índice.
-
-
max_num_levels = 3: o número máximo de níveis de centroide da árvore de clustering de 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 índice 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, quantizer.É 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 é concluída, a linha do índice não fica mais 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 sem bloqueio, 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 depois que 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 transações ou gerar um índice ScaNN sem ativar a criação de índice adiada.
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 ajustado automaticamente, 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 sinalizações no nível da sessão usando o comando
SET LOCAL, o processo considera o valor da sinalização definido no nível do banco de dados. - Se você planeja inserir 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 evitar a criação de um índice ScaNN em uma tabela vazia ou com poucas linhas pelos seguintes motivos:
O índice ScaNN é treinado com dados insuficientes. Isso pode resultar em um recall ruim para pesquisas de similaridade de vetor.
O desempenho de gravação no banco de dados pode ser prejudicado.
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 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 é acionado 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 ajustá-los usando os seguintes parâmetros de plano de consulta 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.