Use embeddings armazenados para gerar índices de vetor do ScaNN e consultar embeddings com o AlloyDB para PostgreSQL.
O índice ScaNN é um índice de quantização baseado em árvore criado pelo Google para pesquisa aproximada de vizinho mais próximo. 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, conclua 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 do 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 adiada de índice 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 instalarvectormanualmente.Se você quiser criar um índice ScaNN de quatro níveis, primeiro ative o recurso Prévia para sua instância do AlloyDB. Para ativar o recurso de prévia, 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 do í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 seguinte comando:
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 o desempenho da pesquisa e realiza a manutenção automática do índice. Se você quiser mudar qualquer 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 de vetor, mas aumenta o tempo de criação do índice.BALANCED: equilibra o tempo de build 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 a manutenção automática, consulte Manter índices vetoriais.(Padrão)
ON: o AlloyDB realiza 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 recall e tempos de criação de índice, crie e ajuste 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. 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 do ScaNN pode ser carregado no mecanismo colunar para acelerar ainda mais a pesquisa de vetor. Escolha uma das opções a seguir:-
(Padrão)
SQ8: oferece um equilíbrio entre a performance da consulta e a perda mínima de recall. Normalmente, esse valor é inferior a 1 ou 2%. -
Prévia
AH: o hash assimétrico (AH) é até quatro vezes mais compactado em comparação comSQ8. Para um desempenho de consulta potencialmente melhor quando o mecanismo colunar está ativado e os dados de índice e tabela são preenchidos no mecanismo colunar, considere isso. Para mais informações, consulte Práticas recomendadas para ajuste do ScaNN. -
FLAT: oferece o maior recall, 99% ou mais, ao custo da performance de 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)
Í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. 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 do 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 a performance da consulta e a perda mínima de recall. Normalmente, esse valor é inferior a 1 ou 2%. -
Prévia
AH: o hash assimétrico (AH) é até quatro vezes mais compactado em comparação comSQ8. Para um desempenho de consulta potencialmente melhor quando o mecanismo colunar está ativado e os dados de índice e tabela são preenchidos no mecanismo colunar, considere isso. Para mais informações, consulte Práticas recomendadas para ajuste do ScaNN. -
FLAT: oferece o maior recall, 99% ou mais, ao custo da performance de 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)
Índice de árvore de quatro níveis
Os índices de árvore de quatro níveis estão em Prévia.
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 = 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 do 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 a performance da consulta e a perda mínima de recall. Normalmente, esse valor é inferior a 1 ou 2%. -
Prévia
AH: o hash assimétrico (AH) é até quatro vezes mais compactado em comparação comSQ8. Para um desempenho de consulta potencialmente melhor quando o mecanismo colunar está ativado e os dados de índice e tabela são preenchidos no mecanismo colunar, considere isso. Para mais informações, consulte Práticas recomendadas para ajuste do ScaNN. -
FLAT: oferece o maior recall, 99% ou mais, ao custo da performance de pesquisa.
-
(Padrão)
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 seu í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 do 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 do ScaNN em uma tabela vazia ou com menos linhas do que o valor da opção de índice num_leaves.
Para contornar essa limitação, ative a criação adiada de índices para permitir que o
AlloyDB adie a criação de índices até que o número de linhas na
tabela atinja o limite definido por num_leaves. Quando 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 recriação do índice acontece em segundo plano, a criação 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 adiada de índices
Para ativar a criação adiada de índices, siga estas etapas:
Ative a flag
scann.enable_index_maintenance(ativada por padrão) e a flagscann.enable_preview_features. A flagscann.enable_preview_featurestambém ativa outros recursos de visualização.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_IDSubstitua:
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 do ScaNN. Se você criar um índice no modo manual, 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 índice usa valores de flags 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 criar um índice do ScaNN.
Forçar a criação de índice em tabelas vazias ou pequenas
O AlloyDB usa validações para evitar a criação de um índice do ScaNN em uma tabela vazia ou com poucas linhas pelos seguintes motivos:
O índice do ScaNN é treinado com dados insuficientes. Isso pode resultar em baixa capacidade de recall para pesquisas de similaridade de vetores.
A performance de gravação no banco de dados pode ser prejudicada.
Recomendamos que você atrase a criação de índices em caso de 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 forçar a criação de índices. A criação forçada de índices exige privilégios de SUPERUSER.
Para forçar a criação do índice, siga estas etapas:
Defina o parâmetro
scann.allow_blocked_operations creationno 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 de
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 seu índice mais rápido, 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 do 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 distância L2. Esses operadores podem usar o índice do
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 esta consulta. Escolha o equivalente de consulta para a 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 a melhor correspondência.
A seguir
- Fazer pesquisas de similaridade vetorial
- Ajustar o desempenho da consulta de vetores
- 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.