O PASE (PostgreSQL ANN search extension) é um plug-in de busca por similaridade vetorial de alto desempenho para o PolarDB for PostgreSQL. Ele implementa dois algoritmos de vizinho mais próximo aproximado (ANN) — IVFFlat e Hierarchical Navigable Small World (HNSW) — para consultar vetores de alta dimensão diretamente no banco de dados com alta velocidade.
O PASE não extrai nem gera vetores de características. Obtenha primeiro os vetores de características das entidades de destino e use o PASE para executar buscas de similaridade em grandes conjuntos de dados vetoriais.
Pré-requisitos
Antes de começar, verifique se você tem:
Um cluster do PolarDB for PostgreSQL
Uma conta privilegiada (necessária para executar as instruções SQL deste tópico)
Conhecimento básico sobre conceitos de machine learning e busca vetorial
Observações de uso
Inchaço de índice: Execute
select pg_relation_size('index_name');e compare o resultado com o tamanho da tabela. Se o índice estiver maior que a tabela e as consultas ficarem mais lentas, reconstrua-o.Desvio de índice após atualizações: Atualizações frequentes de dados podem reduzir a precisão do índice. Reconstrua-o regularmente se precisar de 100% de recall.
Clusterização interna do IVFFlat: Para criar um índice IVFFlat com centroides internos, defina
clustering_type = 1e insira dados na tabela antes de criar o índice.Consultas paralelas elásticas multinó: Apenas a busca sequencial tem suporte para vetores de alta dimensão em consultas paralelas elásticas multinó.
Escolha um algoritmo
O PASE oferece suporte a dois algoritmos ANN. A escolha ideal depende do tamanho do conjunto de dados, da meta de latência e dos requisitos de recall.
|
IVFFlat |
HNSW |
|
|
Mais indicado para |
Casos de uso de alta precisão (ex.: comparação de imagens) |
Grandes conjuntos de dados com requisitos de baixa latência |
|
Meta de latência de consulta |
Até 100 ms |
Até 10 ms |
|
Tamanho do conjunto de dados |
Qualquer tamanho |
Dezenas de milhões de vetores ou mais |
|
Recall de 100% |
Sim, quando o vetor de consulta está no conjunto de dados candidato |
Não; a precisão atinge um platô e ajustes adicionais não a aumentam |
|
Tempo de construção |
Rápido |
Mais lento |
|
Sobrecarga de armazenamento |
Baixa |
Maior (armazena vizinhos do grafo de proximidade) |
|
Controle de precisão |
Totalmente controlável via parâmetros |
Limitado após atingir um limiar |
IVFFlat
O IVFFlat é uma versão simplificada do algoritmo IVFADC. Ele agrupa vetores usando k-means e pesquisa apenas nos clusters mais próximos do vetor de consulta, ignorando clusters distantes para acelerar a busca. A precisão aumenta conforme o número de clusters pesquisados, o que permite ajuste direto.
Funcionamento do IVFFlat:

O IVFFlat aplica clusterização k-means para agrupar vetores em clusters, cada um com um centroide.
Identifica os
ncentroides mais próximos do vetor de consulta.Percorre e classifica todos os vetores nesses
nclusters e retorna oskvetores mais próximos.
Um valor maior para n aumenta a precisão, mas também eleva o custo computacional. Diferentemente do IVFADC, que usa quantização de produto na fase 2 para reduzir o custo de travessia (às custas da precisão), o IVFFlat utiliza busca por força bruta. Isso oferece controle direto sobre o equilíbrio entre precisão e desempenho.
HNSW
O HNSW constrói um grafo hierárquico multicamadas usando o algoritmo Navigable Small World (NSW). Cada camada atua como uma skip list panorâmica sobre a camada inferior, o que permite travessia rápida em grandes conjuntos de dados.
Funcionamento do HNSW:

O HNSW cria uma estrutura com múltiplas camadas (grafos). Cada camada funciona como um panorama e uma skip list da camada abaixo dela.
A partir de um elemento aleatório na camada superior, o HNSW identifica vizinhos e os adiciona a uma lista dinâmica de comprimento fixo, ordenada por distância.
Continua expandindo os vizinhos, reordena a lista após cada adição e mantém apenas os
kmelhores. Quando a lista estabiliza, o HNSW desce para a próxima camada usando o elemento principal como ponto de partida.O processo se repete até concluir a busca na camada inferior.
Depois que a precisão atinge determinado nível, não é possível aumentá-la apenas reconfigurando parâmetros. O HNSW também exige armazenamento adicional para persistir os vizinhos do grafo de proximidade.
Ative o PASE
Execute a seguinte instrução para instalar a extensão PASE:
CREATE EXTENSION pase;
Calcule a similaridade vetorial
Antes de criar um índice, calcule a similaridade vetorial diretamente com o operador <?>. O PASE suporta dois métodos de construção.
O vetor à esquerda deve usar o tipofloat4[]e o vetor à direita deve usar o tipoPASE. Ambos os vetores precisam ter o mesmo número de dimensões; caso contrário, a operação retornará um erro de cálculo de similaridade.
Construção com tipo PASE
O operador <?> calcula a similaridade entre vetores. O tipo de dado PASE aceita até três parâmetros:
Parâmetro 1: O vetor do lado direito (
float4[])Parâmetro 2: Reservado; defina como
0Parâmetro 3: Método de similaridade —
0para distância euclidiana,1para produto escalar (produto interno)
SELECT ARRAY[2, 1, 1]::float4[] <?> pase(ARRAY[3, 1, 1]::float4[]) AS distance;
SELECT ARRAY[2, 1, 1]::float4[] <?> pase(ARRAY[3, 1, 1]::float4[], 0) AS distance;
SELECT ARRAY[2, 1, 1]::float4[] <?> pase(ARRAY[3, 1, 1]::float4[], 0, 1) AS distance;
Construção baseada em string
A construção baseada em string usa dois pontos (:) para separar parâmetros em vez de argumentos de função:
SELECT ARRAY[2, 1, 1]::float4[] <?> '3,1,1'::pase AS distance;
SELECT ARRAY[2, 1, 1]::float4[] <?> '3,1,1:0'::pase AS distance;
SELECT ARRAY[2, 1, 1]::float4[] <?> '3,1,1:0:1'::pase AS distance;
Em '3,1,1:0:1', o primeiro segmento é o vetor, o segundo é o parâmetro reservado (0) e o terceiro é o método de similaridade (0 = Euclidiana, 1 = produto escalar).
Requisito de normalização
Distância euclidiana: Nenhuma normalização necessária.
Produto escalar ou cosseno: Normalize primeiro o vetor original. Para um vetor normalizado, o produto escalar equivale ao valor do cosseno. Por exemplo, se o vetor original for
, ele deve satisfazer:
.
Crie um índice
Índice IVFFlat
CREATE INDEX ivfflat_idx ON vectors_table
USING
pase_ivfflat(vector)
WITH
(clustering_type = 1, distance_type = 0, dimension = 256, base64_encoded = 0, clustering_params = "10,100");
Parâmetros
|
Parâmetro |
Obrigatório |
Padrão |
Descrição |
|
|
Sim |
— |
Modo de clusterização. |
|
|
Não |
|
Método de similaridade. |
|
|
Sim |
— |
Número de dimensões. Máximo: 512. |
|
|
Não |
|
Codificação do vetor. |
|
|
Sim |
— |
Para clusterização externa: o diretório do arquivo de centroides. Para clusterização interna: |
clustering_params para clusterização interna (clustering_type = 1)
Formato: clustering_sample_ratio,k
clustering_sample_ratio: Fração de amostragem com denominador 1.000. Intervalo: (0, 1000]. Por exemplo,1significa uma taxa de amostragem de 1/1000. Um valor maior aumenta a precisão, mas torna a criação do índice mais lenta. Mantenha o total de registros amostrados abaixo de 100.000.k: Número de centroides. Um valor maior aumenta a precisão, mas torna a criação do índice mais lenta. O intervalo recomendado é [100, 1000].
Índice HNSW
CREATE INDEX hnsw_idx ON vectors_table
USING
pase_hnsw(vector)
WITH
(dim = 256, base_nb_num = 16, ef_build = 40, ef_search = 200, base64_encoded = 0);
Parâmetros
|
Parâmetro |
Obrigatório |
Padrão |
Descrição |
|
|
Sim |
— |
Número de dimensões. Máximo: 512. |
|
|
Sim |
— |
Número de vizinhos por elemento. Um valor maior aumenta a precisão, mas torna a criação do índice mais lenta e consome mais armazenamento. Intervalo recomendado: [16, 128]. |
|
|
Sim |
— |
Tamanho do heap durante a criação do índice. Um heap maior aumenta a precisão, mas torna a criação mais lenta. Intervalo recomendado: [40, 400]. |
|
|
Sim |
|
Tamanho do heap durante as consultas. Um valor maior aumenta a precisão, mas reduz o desempenho da consulta. Pode ser substituído no momento da consulta. Comece com |
|
|
Não |
|
Codificação do vetor. |
Consulte vetores
Consulta com índice IVFFlat
Use o operador <#> para consultas com índice IVFFlat. Uma cláusula ORDER BY é obrigatória para que o índice tenha efeito. Os resultados são classificados em ordem crescente de distância.
SELECT id, vector <#> '1,1,1'::pase AS distance
FROM vectors_ivfflat
ORDER BY
vector <#> '1,1,1:10:0'::pase
ASC LIMIT 10;
A string de consulta '1,1,1:10:0' contém três parâmetros separados por dois pontos:
|
Posição |
Valor |
Descrição |
|
1 |
|
Vetor de consulta |
|
2 |
|
Precisão da consulta — intervalo: (0, 1000]. Valores maiores aumentam a precisão, mas reduzem o desempenho da consulta. |
|
3 |
|
Método de similaridade: |
Consulta com índice HNSW
Utilize o operador <?> para consultas com índice HNSW. Uma cláusula ORDER BY é obrigatória para que o índice tenha efeito. Os resultados são classificados em ordem crescente de distância.
SELECT id, vector <?> '1,1,1'::pase AS distance
FROM vectors_ivfflat
ORDER BY
vector <?> '1,1,1:100:0'::pase
ASC LIMIT 10;
A string de consulta '1,1,1:100:0' contém três parâmetros separados por dois pontos:
|
Posição |
Valor |
Descrição |
|
1 |
|
Vetor de consulta |
|
2 |
|
Precisão da consulta — intervalo: (0, ∞). Valores maiores aumentam a precisão, mas reduzem o desempenho da consulta. Comece com |
|
3 |
|
Método de similaridade: |
Apêndice
Calcule o produto escalar (produto interno)
Como o produto escalar de um vetor normalizado equivale ao seu valor de cosseno, a função a seguir serve tanto para buscas por produto escalar quanto por similaridade de cosseno. Ela utiliza um índice HNSW.
CREATE OR REPLACE FUNCTION inner_product_search(query_vector text, ef integer, k integer, table_name text) RETURNS TABLE (id integer, uid text, distance float4) AS $$
BEGIN
RETURN QUERY EXECUTE format('
select a.id, a.vector <?> pase(ARRAY[%s], %s, 1) AS distance from
(SELECT id, vector FROM %s ORDER BY vector <?> pase(ARRAY[%s], %s, 0) ASC LIMIT %s) a
ORDER BY distance DESC;', query_vector, ef, table_name, query_vector, ef, k);
END
$$
LANGUAGE plpgsql;
Crie um índice IVFFlat a partir de um arquivo externo de centroides
Este é um recurso avançado. Carregue um arquivo externo de centroides no diretório especificado do servidor e referencie-o em clustering_params. O formato do arquivo é:
Number of dimensions|Number of centroids|Centroid vector dataset
Exemplo:
3|2|1,1,1,2,2,2
Referências
Hervé Jégou, Matthijs Douze, Cordelia Schmid. Product quantization for nearest neighbor search. IEEE.
Yu.A.Malkov, D.A.Yashunin. Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs. IEEE.