PRODPlataforma BaaS europeia soberanaAbra o painel →

IA nativa · 9 minutos de leitura

Índice HNSW no Postgres: indexe bem para pesquisa vetorial

Affane Daylami · Fondateur · 6 de abril de 2026

Voltar ao blog

HNSW é o algoritmo de indexação recomendado pelo pgvector para pesquisa de vetores de similaridade no Postgres. Este guia mostra como criar um índice HNSW devidamente ajustado. Três opções são importantes: o tipo de coluna de acordo com o tamanho de seus embeddings, os parâmetros m e ef_construction na construção e ef_search em cada solicitação para arbitrar recall e latência.

Este texto em inglês foi gerado automaticamente a partir do original em francês e ainda não foi revisado.
Esta página foi traduzida automaticamente. A versão em inglês é oficial.

A pesquisa vetorial nativa do Aurabase (RAG, pgvector, embeddings) depende deste mesmo mecanismo de indexação, descrito em detalhes na página Native AI no Postgres. Este guia assume uma tabela Postgres com pgvector já instalado, uma coluna do tipo vectore pelo menos alguns milhares de linhas. Abaixo, uma varredura sequencial simples costuma ser mais rápida que um índice aproximado.

O essencial

  • O HNSW não requer nenhuma fase de treinamento, ao contrário do IVFFlat: o índice é construído sobre inserções, disponíveis no pgvector desde a versão 0.5.0.
  • Dois parâmetros definem a qualidade do índice na construção: m (conexões por nó, padrão 16) e ef_construction (largura de pesquisa na construção, padrão 64).
  • Um terceiro parâmetro, hnsw.ef_search (pgvector padrão: 40), é ajustado para cada solicitação, sem reconstruir o índice, para arbitrar o recall e a latência.
  • pgvector limita a indexação HNSW do tipo vector a 2.000 dimensões. Além disso (uma incorporação com dimensões 3072, por exemplo), é necessário um cast para halfvec para indexar.
  • pgvector 0.8.6 é a versão incorporada na imagem do locatário Aurabase Postgres, verificada diretamente no Dockerfile em 24 de agosto de 2026.
#
Entenda

O que é um índice HNSW no pgvector?

HNSW significa Mundo Pequeno Navegável Hierárquico. É um índice gráfico: cada vetor torna-se um nó conectado aos seus vizinhos mais próximos, organizado em diversas camadas sobrepostas. Uma pesquisa começa no topo do gráfico, na camada mais esparsa, e depois desce, camada por camada, até os vizinhos mais relevantes. O tempo de busca torna-se assim quase logarítmico, não linear ao longo do número de linhas.

IVFFlat, o outro índice do pgvector, funciona de forma diferente: ele divide o espaço vetorial em listas determinadas por uma passagem de treinamento em uma amostra existente, antes de poder indexar qualquer coisa. O HNSW não possui essa restrição, cada inserção enriquece diretamente o gráfico, o que torna mais simples operar em uma tabela que cresce continuamente. Por outro lado, um índice HNSW consome mais memória e leva mais tempo para ser construído do que um IVFFlat equivalente no mesmo volume.

pgvector introduz suporte HNSW na versão 0.5.0. Versões posteriores adicionam recursos úteis para este guia: o tipo halfvec (0.7.0) para indexar além de 2.000 dimensões e o parâmetro hnsw.iterative_scan (0.8.0) para melhorar o recall em consultas filtradas. Se você comparar o pgvector com uma base vetorial dedicada antes de decidir, nossa comparação pgvector vs Pinecone, Weaviate e Qdrant detalha as compensações.

#
Passo 1

Verifique sua versão do pgvector antes de criar o índice

Confirme a versão do pgvector instalada primeiro. Uma extensão muito antiga faz com que alguns recursos deste guia falhem silenciosamente, principalmente halfvec e hnsw.iterative_scan.

psqlsql
SELECT extversion FROM pg_extension WHERE extname = 'vector';

O HNSW existe desde o pgvector 0.5.0. O tipo halfvec, necessário para indexar embeddings além de 2.000 dimensões, requer pelo menos a versão 0.7.0. O parâmetro hnsw.iterative_scan solicita a versão 0.8.0.

Em projetos Aurabase, a questão não se coloca: a imagem Postgres incorpora pgvector 0.8.6, tanto no cluster Postgres compartilhado (docker/Postgres.Dockerfile, construído diretamente em pgvector/pgvector:0.8.6-pg16-bookworm) quanto nas instâncias Postgres 16 CNPG dedicadas por projeto (docker/Postgres.CNPG.Dockerfile, que herda pgvector 0.8.6 da imagem oficial do CloudNativePG). Verificado em ambos Dockerfiles em 24 de agosto de 2026.

#
Etapa 2

Escolha o tipo certo de coluna de acordo com o tamanho dos seus embeddings

O tipo de coluna depende do tamanho dos seus embeddings, não apenas do modelo que os gera. pgvector armazena um vetor clássico do tipo vector, com um limite de 16.000 dimensões em armazenamento. Mas a indexação HNSW neste tipo é limitada a 2.000 dimensões: além disso, CREATE INDEX falha.

Os modelos de incorporação comuns geralmente excedem esse limite: text-embedding-3-large do OpenAI ou gemini-embedding-2 do Google produzem nativamente até 3.072 dimensões. Para indexar esses vetores com HNSW, converta a coluna em halfvec (precisão de armazenamento reduzida pela metade), o que aumenta o limite de indexação bem além de 2.000 dimensões.

DimensõesColunaHNSW no vetorRequer elenco
768incorporação_768SimNão
1536incorporação_1536SimNão
3072incorporação_3072Não (> 2.000 escurece)Sim, elenco::halfvec(3072)

O mecanismo Aurabase RAG ilustra esse compromisso na produção: três classes de dimensões suportadas (768, 1536, 3072), armazenadas em três colunas distintas da mesma tabela embeddings. As colunas 768 e 1536 são indexadas diretamente em HNSW no tipo vector. A coluna 3072 é indexada por meio de uma conversão ::halfvec(3072), precisamente para contornar o limite de dimensão de 2.000.

migration.sqlsql
CREATE INDEX idx_embeddings_vec_768 ON embeddings
  USING hnsw (embedding_768 vector_cosine_ops)
  WHERE embedding_768 IS NOT NULL;

CREATE INDEX idx_embeddings_vec_1536 ON embeddings
  USING hnsw (embedding_1536 vector_cosine_ops)
  WHERE embedding_1536 IS NOT NULL;

CREATE INDEX idx_embeddings_vec_3072 ON embeddings
  USING hnsw ((embedding_3072::halfvec(3072)) halfvec_cosine_ops)
  WHERE embedding_3072 IS NOT NULL;

Para obter detalhes sobre a ingestão (fragmentação, chamada para o provedor de incorporação, inserção), consulte o tutorial do pipeline RAG em pgvector.

#
Etapa 3

Crie o índice com os parâmetros m e ef_construction

A sintaxe mínima é suficiente para um primeiro índice, com os valores padrão de pgvector.

psqlsql
CREATE INDEX ON items
  USING hnsw (embedding vector_cosine_ops);

pgvector então aplica m = 16 e ef_construction = 64. Para ajustar esses valores explicitamente, use a cláusula WITH:

psqlsql
CREATE INDEX ON items
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 24, ef_construction = 100);
Acelere uma grande construção

Antes de construir um índice HNSW em uma tabela grande, aumente temporariamente maintenance_work_mem para a sessão: esta é, de acordo com a própria documentação do pgvector, a alavanca mais direta para reduzir o tempo de construção.

O que o parâmetro m muda?

m define o número máximo de conexões que cada nó no gráfico mantém por camada. Um valor mais alto densifica o gráfico: a recuperação aumenta, mas a memória consumida e o tempo de construção também aumentam, de forma aproximadamente linear. O padrão (16) é adequado para a maioria dos casos. Subir para 24 ou 32 é especialmente justificado em grandes embeddings, onde a distinção entre vizinhos próximos e distantes se torna mais precisa.

O que ef_construction muda?

ef_construction define o tamanho da lista de candidatos explorada durante a construção do índice, para cada nó inserido. Um valor mais alto melhora a qualidade do gráfico final, portanto o potencial recall, ao custo de um tempo de construção mais longo. Ao contrário de m, este parâmetro não tem custo na hora da consulta: é um investimento único, pago apenas uma vez na criação do índice.

Índices parciais para diversas classes de dimensão na mesma tabela

Quando uma tabela armazena várias colunas de vetor (uma por classe de dimensão, como faz o Aurabase), indexe cada coluna separadamente com uma cláusula WHERE colonne IS NOT NULL. Este índice parcial evita a indexação de linhas vazias para classes não utilizadas por uma determinada linha, o que reduz o tamanho do índice e agiliza sua construção sem custar nada em recall.

A escolha da classe do operador (vector_cosine_ops, vector_l2_ops ou vector_ip_ops) deve corresponder à métrica na qual o modelo de incorporação foi treinado. Os modelos de incorporação de texto mais recentes são treinados para similaridade de cosseno: vector_cosine_ops (ou halfvec_cosine_ops em uma coluna convertida) é, portanto, a escolha padrão mais segura.

#
Etapa 4

Defina ef_search no momento da consulta

ef_search é definido em cada consulta, não quando o índice é criado. Define o tamanho da lista de candidatos explorados durante a busca: quanto maior for, melhor será o recall, ao custo de maior latência. pgvector define seu valor padrão para 40.

psqlsql
SET LOCAL hnsw.ef_search = 100;

SELECT id, content
FROM embeddings
ORDER BY embedding <=> '[...]'::vector
LIMIT 10;

40 raramente é suficiente assim que uma consulta combina pesquisa vetorial com um filtro WHERE aplicado após a varredura do índice (em um namespace, um locatário ou qualquer outro critério de metadados). A varredura HNSW traz de volta ef_search candidatos brutos e, em seguida, o filtro descarta parte deles. Se poucos candidatos sobreviverem, o LIMIT final acaba sendo insuficientemente preenchido.

O mecanismo Aurabase RAG, portanto, expande ef_search dinamicamente de acordo com o top_ksolicitado, em vez de manter o valor fixo de 40: ef = max(top_k × 4, 64). Uma busca pelos 5 resultados mais próximos usa ef_search = 64; uma pesquisa pelos 50 principais usos ef_search = 200. Essa fórmula permanece ajustável por variável de ambiente para implantações que precisam de outra compensação entre recall/latência.

O pgvector 0.8 adiciona uma segunda alavanca para este mesmo problema: hnsw.iterative_scan. No modo strict_order ou relaxed_order, a busca amplia gradativamente sua busca até reunir resultados suficientes após a filtragem, em vez de parar em uma lista fixa de candidatos. Aurabase ativa por padrão em strict_order, mas protege a chamada em um savepoint. Em uma versão do pgvector anterior a 0.8, onde esse parâmetro não existe, a consulta continua no modo degradado em vez de falhar.

#
Vá mais longe

Construa o pipeline RAG completo

Este índice HNSW é apenas uma parte do pipeline RAG completo: fragmentação, geração de incorporação, ingestão e pesquisa. Nosso tutorial passo a passo constrói esse pipeline de ponta a ponta no pgvector, desde a primeira inserção até a consulta de similaridade. A documentação técnica também detalha todos os recursos de IA nativos do Aurabase construídos no Postgres.

#
Perguntas frequentes

Perguntas frequentes

HNSW ou IVFFlat: qual escolher com pgvector?+
O HNSW é adequado para a grande maioria dos casos de pesquisa vetorial em produção: melhor recuperação com latência igual, sem fase de treinamento anterior e boa tolerância a tabelas que crescem continuamente. IVFFlat permanece relevante quando a memória disponível é muito restrita, ao custo de uma recuperação geralmente menor e de um novo treinamento necessário se a distribuição dos dados mudar significativamente.
Quanta memória planejar para um índice HNSW?+
A ordem de grandeza depende diretamente de me do número de vetores indexados: cada nó armazena até m conexões por camada, além do próprio vetor. Para obter uma estimativa confiável do seu volume real, crie o índice em um subconjunto representativo dos seus dados. Em seguida, meça seu tamanho com pg_relation_size() em vez de confiar em uma regra prática não medida.
Podemos indexar incorporações de mais de 2.000 dimensões com HNSW?+
Não diretamente no tipo de vetor: pgvector se recusa a construir um índice HNSW além de 2.000 dimensões neste tipo. A solução é converter a coluna em halfvec no momento da criação do índice, o que aumenta o limite de indexação ao reduzir pela metade a precisão do armazenamento. Esta é exatamente a abordagem usada na produção da classe de incorporação de 3072 dimensões do Aurabase.

PRONTO PARA IMPLEMENTAR?

Seu back-end em cinco minutos.

Não é necessário cartão de crédito · 500 MB grátis · 50.000 MAU