Este documento mostra como ajustar seus índices para alcançar um desempenho de consulta mais rápido e um recall melhor.
Ajustar um índice ScaNN
O índice ScaNN usa indexação baseada em quantização de árvore. Nas técnicas de quantização de árvore, os índices aprendem uma árvore de pesquisa junto com uma função de quantização (ou hash). Quando você executa uma consulta, a árvore de pesquisa é usada para reduzir o espaço de pesquisa, e a quantização é usada para compactar o tamanho do índice. Essa remoção acelera a pontuação da similaridade (ou seja, distância) entre o vetor de consulta e os vetores do banco de dados.
Para alcançar uma alta taxa de consultas por segundo (QPS) e um recall alto com suas consultas de vizinho mais próximo, particione a árvore do seu índice ScaNN
da maneira mais adequada aos seus dados e consultas.
Antes de criar um índice ScaNN
, faça o seguinte:
- Verifique se uma tabela com seus dados já foi criada.
- Verifique se o valor definido para a flag
maintenance_work_mem
eshared_buffers
é menor que a memória total da máquina para evitar problemas ao gerar o índice.
Parâmetros de ajuste
Os parâmetros de índice e flags de banco de dados a seguir são usados juntos para encontrar o equilíbrio certo de recall e QPS. Todos os parâmetros se aplicam aos dois tipos de índice ScaNN
.
Parâmetro de ajuste | Descrição | Tipo de parâmetro |
---|---|---|
num_leaves |
O número de partições a serem aplicadas a este índice. O número de partições aplicadas ao criar um índice afeta o desempenho dele. Ao aumentar as partições para um determinado número de vetores, você cria um índice mais refinado, o que melhora a recuperação e o desempenho da consulta. No entanto, isso aumenta o tempo de criação do índice. Como as árvores de três níveis são criadas mais rápido do que as de dois níveis, é possível aumentar o num_leaves_value ao criar um índice de árvore de três níveis para melhorar o desempenho.
|
Criação de índice |
quantizer |
O tipo de quantizador que você quer usar para a árvore K-means. O valor padrão é SQ8 para melhorar o desempenho da consulta.Defina como FLAT para melhorar a capacidade de recall. |
Criação de índice |
enable_pca |
Ativa a análise de componentes principais (PCA), uma técnica de redução de dimensão usada para reduzir automaticamente o tamanho do encadeamento quando possível. Essa opção é ativada por padrão. Defina como false se você notar uma deterioração na capacidade de recall. |
Criação de índice |
scann.num_leaves_to_search |
A flag do banco de dados controla a compensação entre recall e QPS. O valor padrão é 1% do valor definido em num_leaves . Quanto maior o valor definido, melhor o recall, mas isso resulta em QPS menor e vice-versa. |
Tempo de execução da consulta |
scann.max_top_neighbors_buffer_size |
A flag do banco de dados especifica o tamanho do cache usado para melhorar o desempenho de consultas filtradas, classificando ou ordenando os vizinhos candidatos verificados na memória em vez do disco. O valor padrão é 20000 . Quanto maior o valor definido, melhor será o QPS em consultas filtradas, mas isso resulta em maior uso de memória e vice-versa. |
Tempo de execução da consulta |
scann.pre_reordering_num_neighbors |
Quando definida, a flag do banco de dados especifica o número de vizinhos candidatos a serem considerados durante as etapas de reordenação depois que a pesquisa inicial identifica um conjunto de candidatos. Defina um valor maior que o número de vizinhos que você quer que a consulta retorne. Conjuntos de valores mais altos resultam em um recall melhor, mas essa abordagem resulta em QPS menor. |
Tempo de execução da consulta |
max_num_levels |
O número máximo de níveis da árvore de clusterização k-means.
|
Criação de índice |
Ajustar um índice ScaNN
Confira os exemplos a seguir para índices ScaNN
de dois e três níveis que mostram como os parâmetros de ajuste são definidos:
Índice de dois níveis
SET LOCAL scann.num_leaves_to_search = 1;
SET LOCAL scann.pre_reordering_num_neighbors=50;
CREATE INDEX my-scann-index ON my-table
USING scann (vector_column cosine)
WITH (num_leaves = [power(1000000, 1/2)]);
Índice de três níveis
SET LOCAL scann.num_leaves_to_search = 10;
SET LOCAL scann.pre_reordering_num_neighbors=50;
CREATE INDEX my-scann-index ON my-table
USING scann (vector_column cosine)
WITH (num_leaves = [power(1000000, 2/3)], max_num_levels = 2);
Qualquer operação de inserção ou atualização em uma tabela em que um índice ScaNN
já foi
gerado afeta a forma como a árvore aprendida otimiza o índice. Se
a tabela estiver sujeita a atualizações ou inserções frequentes, recomendamos
reindexar periodicamente o índice ScaNN
atual para melhorar a acurácia de recall.
É possível monitorar as métricas de índice para determinar a quantidade de mutações criadas desde que o índice foi criado e, em seguida, reindexar de acordo. Para mais informações sobre métricas, consulte Métricas de índice vetorial.
Práticas recomendadas para ajuste
As recomendações para ajuste do índice variam de acordo com o tipo de índice ScaNN
que você planeja usar. Esta seção oferece recomendações sobre como ajustar os parâmetros de índice para um equilíbrio ideal entre recall e QPS.
Índice de árvore de dois níveis
Para aplicar recomendações que ajudam a encontrar os valores ideais de num_leaves
e num_leaves_to_search
para seu conjunto de dados, siga estas etapas:
- Crie o índice
ScaNN
comnum_leaves
definido como a raiz quadrada da contagem de linhas da tabela indexada. - Execute as consultas de teste, aumentando o valor de
scann.num_of_leaves_to_search
até atingir o intervalo de recall desejado, por exemplo, 95%. Para mais informações sobre como analisar suas consultas, consulte Analisar suas consultas. - Anote a proporção entre
scann.num_leaves_to_search
enum_leaves
, que será usada nas próximas etapas. Essa proporção fornece uma aproximação do conjunto de dados que vai ajudar você a alcançar a meta de recall.
Se você estiver trabalhando com vetores de alta dimensão (500 dimensões ou mais) e quiser melhorar o recall, ajuste o valor descann.pre_reordering_num_neighbors
. Como ponto de partida, defina o valor como100 * sqrt(K)
, em queK
é o limite definido na consulta. - Se o QPS estiver muito baixo depois que as consultas atingirem uma taxa de recall desejada, siga estas etapas:
- Recrie o índice, aumentando o valor de
num_leaves
escann.num_leaves_to_search
de acordo com as seguintes orientações:- Defina
num_leaves
como um fator maior da raiz quadrada da contagem de linhas. Por exemplo, se o índice tivernum_leaves
definido como a raiz quadrada da contagem de linhas, tente definir como o dobro da raiz quadrada. Se o valor já for duplo, tente definir como o triplo da raiz quadrada. - Aumente
scann.num_leaves_to_search
conforme necessário para manter a proporção comnum_leaves
, que você anotou na etapa 3. - Defina
num_leaves
como um valor menor ou igual à contagem de linhas dividida por 100.
- Defina
- Execute as consultas de teste novamente.
Enquanto executa as consultas de teste, tente reduzir
scann.num_leaves_to_search
e encontre um valor que aumente as QPS e mantenha o recall alto. Teste valores diferentes descann.num_leaves_to_search
sem recriar o índice.
- Recrie o índice, aumentando o valor de
- Repita a etapa 4 até que o QPS e o intervalo de recall atinjam valores aceitáveis.
Índice de árvore de três níveis
Além das recomendações para o índice de árvore de dois níveis ScaNN
, use as orientações e etapas a seguir para ajustar o índice:
- Aumentar o
max_num_levels
de1
para uma árvore de dois níveis para2
para uma árvore de três níveis reduz significativamente o tempo de criação de um índice, mas à custa da acurácia do recall. Definamax_num_levels
usando a seguinte recomendação:- Defina o valor como
2
se o número de linhas de vetor exceder 100 milhões. - Defina o valor como
1
se o número de linhas de vetor for inferior a 10 milhões. - Defina como
1
ou2
se o número de linhas de vetor estiver entre 10 milhões e 100 milhões, com base no equilíbrio entre o tempo de criação do índice e a acurácia de recall necessária.
- Defina o valor como
Para aplicar recomendações e encontrar o valor ideal dos parâmetros de índice num_leaves
e max_num_levels
, siga estas etapas:
Crie o índice
ScaNN
com as seguintes combinações denum_leaves
emax_num_levels
com base no seu conjunto de dados:- linhas de vetor maiores que 100 milhões de linhas: defina
max_num_levels
como2
enum_leaves
comopower(rows, ⅔)
. - linhas de vetor menores que 100 milhões de linhas: defina
max_num_levels
como1
enum_leaves
comosqrt(rows)
. - linhas de vetor entre 10 milhões e 100 milhões de linhas: comece definindo
max_num_levels
como1
enum_leaves
comosqrt(rows)
.
- linhas de vetor maiores que 100 milhões de linhas: defina
Execute suas consultas de teste. Para mais informações sobre como analisar consultas, consulte Analisar suas consultas.
Se o tempo de criação do índice for satisfatório, mantenha o valor
max_num_levels
e teste o valornum_leaves
para ter uma acurácia de recall ideal.Se você não estiver satisfeito com o tempo de criação do índice, faça o seguinte:
Se o valor de
max_num_levels
for1
, descarte o índice. Reconstrua o índice com o valormax_num_levels
definido como2
.Execute as consultas e ajuste o valor de
num_leaves
para ter uma acurácia de recall ideal.Se o valor de
max_num_levels
for2
, descarte o índice. Recrie o índice com o mesmo valormax_num_levels
e ajuste o valornum_leaves
para uma acurácia de recall ideal.
Ajustar um índice IVF
Ajustar os valores definidos para os parâmetros lists
, ivf.probes
e quantizer
pode ajudar a otimizar o desempenho do aplicativo:
Parâmetro de ajuste | Descrição | Tipo de parâmetro |
---|---|---|
lists |
O número de listas criadas durante a criação do índice. O ponto de partida para definir esse valor é (rows)/1000 para até um milhão de linhas e sqrt(rows) para mais de um milhão de linhas. |
Criação de índice |
quantizer |
O tipo de quantizador que você quer usar para a árvore K-means. O valor padrão é SQ8 para melhorar o desempenho da consulta. Defina como FLAT para facilitar a memorização. |
Criação de índice |
ivf.probes |
o número de listas mais próximas a serem analisadas durante a pesquisa. O ponto de partida desse valor é sqrt(lists) . |
Tempo de execução da consulta |
Considere o exemplo a seguir, que mostra um índice IVF
com os parâmetros de ajuste definidos:
SET LOCAL ivf.probes = 10;
CREATE INDEX my-ivf-index ON my-table
USING ivf (vector_column cosine)
WITH (lists = 100, quantizer = 'SQ8');
Ajustar um índice IVFFlat
Ajustar os valores definidos para os parâmetros lists
e ivfflat.probes
pode ajudar a otimizar o desempenho do aplicativo:
Parâmetro de ajuste | Descrição | Tipo de parâmetro |
---|---|---|
lists |
O número de listas criadas durante a criação do índice. O ponto de partida para definir esse valor é (rows)/1000 para até um milhão de linhas e sqrt(rows) para mais de um milhão de linhas. |
Criação de índice |
ivfflat.probes |
O número de listas mais próximas a serem analisadas durante a pesquisa. O ponto de partida desse valor é sqrt(lists) . |
Tempo de execução da consulta |
Antes de criar um índice IVFFlat
, verifique se a flag max_parallel_maintenance_workers
do banco de dados está definida com um valor suficiente para acelerar a criação do índice em tabelas grandes.
Considere o exemplo a seguir, que mostra um índice IVFFlat
com os parâmetros de ajuste definidos:
SET LOCAL ivfflat.probes = 10;
CREATE INDEX my-ivfflat-index ON my-table
USING ivfflat (vector_column cosine)
WITH (lists = 100);
Ajustar um índice HNSW
Ajustar os valores definidos para os parâmetros m
, ef_construction
e hnsw.ef_search
pode ajudar a otimizar a performance do aplicativo.
Parâmetro de ajuste | Descrição | Tipo de parâmetro |
---|---|---|
m |
O número máximo de conexões de um nó no gráfico. Comece com o valor padrão 16 (padrão) e teste valores mais altos com base no tamanho do seu conjunto de dados. |
Criação de índice |
ef_construction |
O tamanho da lista dinâmica de candidatos mantida durante a construção do gráfico, que atualiza constantemente os melhores candidatos atuais para vizinhos mais próximos de um nó. Defina esse valor como qualquer valor maior que o dobro do valor de m , por exemplo, 64 (padrão). |
Criação de índice |
ef_search |
O tamanho da lista dinâmica de candidatos usada durante a pesquisa. Comece definindo esse valor como m ou ef_construction e mude enquanto observa o recall. O valor padrão é 40 . |
Tempo de execução da consulta |
Considere o exemplo a seguir, que mostra um índice hnsw
com os parâmetros de ajuste definidos:
SET LOCAL hnsw.ef_search = 40;
CREATE INDEX my-hnsw-index ON my-table
USING hnsw (vector_column cosine)
WITH (m = 16, ef_construction = 200);
Analisar suas consultas
Use o comando EXPLAIN ANALYZE
para analisar os insights de consulta, conforme mostrado no exemplo de consulta SQL a seguir.
EXPLAIN ANALYZE SELECT result-column FROM my-table
ORDER BY EMBEDDING_COLUMN ::vector
USING INDEX my-scann-index
<-> embedding('textembedding-gecko@003', 'What is a database?')
LIMIT 1;
O exemplo de resposta QUERY PLAN
inclui informações como o tempo gasto, o número de linhas verificadas ou retornadas e os recursos usados.
Limit (cost=0.42..15.27 rows=1 width=32) (actual time=0.106..0.132 rows=1 loops=1)
-> Index Scan using my-scann-index on my-table (cost=0.42..858027.93 rows=100000 width=32) (actual time=0.105..0.129 rows=1 loops=1)
Order By: (embedding_column <-> embedding('textgecko@003', 'What is a database?')::vector(768))
Limit value: 1
Planning Time: 0.354 ms
Execution Time: 0.141 ms
Visualizar métricas de índice vetorial
Use as métricas de índice de vetor para analisar a performance dele, identificar áreas de melhoria e ajustar o índice com base nas métricas, se necessário.
Para conferir todas as métricas de índice de vetor, execute a seguinte consulta SQL, que usa a visualização pg_stat_ann_indexes
:
SELECT * FROM pg_stat_ann_indexes;
Para mais informações sobre a lista completa de métricas, consulte Métricas de índice vetorial.