PostgreSQL com pgvector: como armazenar embeddings e fazer busca vetorial
Veja como instalar e usar pgvector no PostgreSQL, armazenar embeddings, consultar similaridade e escolher índices para busca vetorial.

Adicionar busca semântica a uma aplicação não exige, necessariamente, a adoção imediata de um novo banco de dados.
Se o produto já usa PostgreSQL, o pgvector permite armazenar embeddings, calcular similaridade e aplicar filtros relacionais no mesmo ambiente em que vivem usuários, permissões, documentos e demais regras de negócio.
Essa combinação é especialmente interessante para protótipos, sistemas internos e aplicações de IA que precisam unir busca vetorial a transações, joins e consultas SQL.
Porém, o simples ato de criar uma coluna do tipo vector não garante desempenho: é preciso escolher a métrica correta, entender a diferença entre busca exata e aproximada e medir o resultado com dados reais.
Neste guia, você vai montar uma implementação funcional de pgvector no PostgreSQL, consultar vetores por similaridade, criar índices HNSW e IVFFlat e descobrir quando essa arquitetura faz sentido — e quando uma solução vetorial dedicada pode ser mais adequada.
O que é pgvector?
O pgvector é uma extensão de código aberto que adiciona busca por similaridade vetorial ao PostgreSQL.
Ela cria tipos de dados próprios para vetores e operadores de distância, permitindo que uma consulta SQL ordene registros de acordo com a proximidade entre seus embeddings.
Um embedding é uma sequência de números que representa características semânticas de um texto, imagem ou outro objeto.
Conteúdos com significados próximos tendem a ocupar regiões próximas no espaço vetorial. Se esse conceito ainda for novo para você, consulte nosso guia sobre o que são embeddings em IA.
Segundo a documentação oficial do pgvector, a extensão oferece busca exata e aproximada, além de distâncias euclidiana, cosseno, produto interno e outras métricas.
Seu diferencial não é apenas guardar vetores: é combiná-los aos recursos maduros do PostgreSQL, como transações, índices tradicionais, controle de acesso e recuperação.
Quando usar pgvector no PostgreSQL
O pgvector costuma ser uma escolha prática quando a aplicação já depende do PostgreSQL e a busca vetorial precisa conviver de perto com dados relacionais.
Um catálogo pode filtrar por estoque e categoria antes de ordenar produtos semanticamente; uma plataforma corporativa pode restringir documentos por empresa e permissão; um assistente pode recuperar apenas trechos pertencentes ao usuário autenticado.
- Você quer reduzir componentes na arquitetura inicial.
- Consistência transacional entre o objeto e seu embedding é importante.
- As consultas dependem de filtros, joins e regras de autorização.
- A equipe já domina SQL, operação e monitoramento do PostgreSQL.
- O volume e a taxa de consultas cabem na capacidade planejada do banco.
Isso não significa que a extensão substitua qualquer banco de dados vetorial.
Em escalas muito altas, com distribuição entre regiões, ingestão maciça ou funcionalidades vetoriais especializadas, outra tecnologia pode trazer vantagens.
A decisão deve partir dos requisitos e de testes, não da popularidade da ferramenta.
Como instalar e habilitar a extensão
Primeiro, o pacote do pgvector precisa estar instalado no servidor ou disponível no serviço gerenciado. A forma de instalação varia entre Linux, contêineres e provedores de nuvem.
Depois disso, conecte-se ao banco desejado com um usuário autorizado e execute:
CREATE EXTENSION IF NOT EXISTS vector;
O comando segue o mecanismo padrão de extensões do PostgreSQL. Em produção, confirme previamente a versão do PostgreSQL e do pgvector suportada pelo ambiente, aplique a mudança por migração e teste restauração e replicação.
Para revisar a base antes de avançar, veja também o guia de PostgreSQL para iniciantes.
Como armazenar embeddings
Crie uma coluna vector(n), em que n é exatamente a dimensão retornada pelo modelo de embeddings.
O exemplo abaixo usa três dimensões para que os valores sejam legíveis. Em uma aplicação real, substitua esse número pela dimensão do modelo escolhido.
CREATE TABLE documentos (
id bigserial PRIMARY KEY,
conta_id bigint NOT NULL,
titulo text NOT NULL,
conteudo text NOT NULL,
embedding vector(3) NOT NULL,
criado_em timestamptz NOT NULL DEFAULT now()
);
INSERT INTO documentos (conta_id, titulo, conteudo, embedding)
VALUES
(42, 'Troca de senha', 'Procedimento para redefinir a senha', '[0.12,0.81,0.22]'),
(42, 'Segunda via', 'Como emitir uma nova fatura', '[0.75,0.10,0.36]');

Guarde também o texto original, a identificação do modelo e os metadados necessários para filtros.
O vetor não é uma versão reversível do conteúdo. Registrar o modelo e a versão ajuda a planejar uma futura reindexação, pois embeddings produzidos por modelos ou configurações diferentes não devem ser comparados como se pertencessem ao mesmo espaço.
Como fazer busca vetorial com SQL
Por padrão, sem um índice vetorial aproximado, o pgvector calcula uma busca exata.
Para localizar os registros mais próximos de um vetor de consulta usando distância de cosseno, ordene pela expressão com o operador <=> e aplique um limite:
SELECT
id,
titulo,
1 - (embedding <=> '[0.10,0.78,0.25]') AS similaridade
FROM documentos
WHERE conta_id = 42
ORDER BY embedding <=> '[0.10,0.78,0.25]'
LIMIT 5;
A aplicação deve gerar o embedding da pergunta com o mesmo modelo utilizado na indexação. Parametrize o vetor e os filtros no driver, em vez de concatenar valores em uma string SQL.
O cálculo 1 - distância produz uma pontuação intuitiva quando a distância de cosseno é usada, mas não transforme um limiar arbitrário em verdade universal: valide o ponto de corte com consultas reais.
Operadores e métricas de distância
| Operador | Métrica | Classe de operador do índice |
|---|---|---|
<-> | Distância euclidiana (L2) | vector_l2_ops |
<#> | Produto interno negativo | vector_ip_ops |
<=> | Distância de cosseno | vector_cosine_ops |
<+> | Distância L1 | vector_l1_ops |
A métrica deve acompanhar o modo como o modelo foi treinado e recomendado pelo fornecedor.
Distância de cosseno é comum para texto porque compara a direção dos vetores; distância L2 considera a separação geométrica; produto interno pode ser apropriado para vetores normalizados e alguns modelos específicos.
Trocar apenas o operador durante um teste pode mudar completamente a ordenação.
Busca exata ou aproximada
A busca exata compara a consulta com todos os candidatos compatíveis e oferece recuperação perfeita dentro da métrica escolhida.
Ela é simples e serve como referência de qualidade, mas o custo cresce com a quantidade de vetores.
Já a busca aproximada usa uma estrutura de índice para visitar apenas parte do espaço, reduzindo latência em troca da possibilidade de não retornar algum vizinho verdadeiro.
Os dois métodos principais do pgvector são HNSW e IVFFlat. Como ocorre com outros índices em banco de dados, eles aceleram leituras ao custo de armazenamento, construção e manutenção adicional.
Índice HNSW
HNSW constrói um grafo multicamada para navegar até regiões promissoras do espaço vetorial.
Em geral, oferece uma relação forte entre velocidade e recall, não exige uma fase de treinamento e pode ser criado mesmo antes de a tabela receber dados.
Em contrapartida, demora mais para construir e consome mais memória que IVFFlat.
CREATE INDEX documentos_embedding_hnsw
ON documentos
USING hnsw (embedding vector_cosine_ops);
Parâmetros de construção, como m e ef_construction, alteram custo, tamanho e qualidade.
Na consulta, hnsw.ef_search controla quantos candidatos são explorados. Comece com os padrões e ajuste somente após medir recall e latência.
Índice IVFFlat
IVFFlat divide vetores em listas e pesquisa apenas algumas delas. Costuma ser construído mais rapidamente e usar menos memória, mas sua qualidade depende de dados representativos já existentes durante a criação.
O número de listas e o parâmetro de consulta ivfflat.probes precisam ser calibrados conforme o volume e a distribuição dos embeddings.
CREATE INDEX documentos_embedding_ivfflat
ON documentos
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);

| Critério | HNSW | IVFFlat |
|---|---|---|
| Treinamento prévio | Não | Depende de dados existentes |
| Construção | Mais lenta | Mais rápida |
| Memória | Maior consumo | Menor consumo |
| Velocidade e recall | Geralmente melhor relação | Mais dependente de listas e probes |
Filtros, metadados e joins
Filtros são uma das maiores razões para manter os vetores no PostgreSQL.
A consulta pode restringir por conta, idioma, categoria, status ou intervalo de datas antes de ordenar por distância. Crie índices convencionais nas colunas seletivas:
CREATE INDEX documentos_conta_id_idx ON documentos (conta_id);
SELECT d.id, d.titulo
FROM documentos AS d
JOIN contas AS c ON c.id = d.conta_id
WHERE c.ativa = true
AND d.conta_id = 42
ORDER BY d.embedding <=> '[0.10,0.78,0.25]'
LIMIT 10;
Em índices aproximados, o filtro pode eliminar resultados depois da varredura do índice e devolver menos linhas do que o limite solicitado.
A documentação do pgvector oferece varreduras iterativas para ampliar automaticamente a exploração quando isso acontece. Também vale considerar índice parcial ou particionamento quando certos filtros são muito frequentes.
Segurança continua sendo regra: não dependa somente da busca vetorial para isolar dados entre clientes.
pgvector em um pipeline RAG
Em uma arquitetura de RAG em IA, documentos são divididos em trechos, transformados em embeddings e gravados com fonte e metadados.
Quando chega uma pergunta, a aplicação gera outro embedding, recupera os trechos mais próximos e os envia ao modelo generativo como contexto.
- Extraia e limpe os documentos.
- Divida o conteúdo em trechos com contexto suficiente.
- Gere embeddings em lote e registre o modelo utilizado.
- Armazene texto, vetor, fonte, permissões e versão.
- Consulte candidatos com filtros obrigatórios.
- Avalie ou reordene os resultados antes de gerar a resposta.
O banco resolve a recuperação, não toda a qualidade do RAG. Chunking ruim, metadados incompletos ou perguntas fora do domínio continuarão produzindo contexto fraco.
Para cenários mais exigentes, o artigo sobre reranking em RAG explica como aplicar um segundo modelo aos candidatos recuperados.
Busca híbrida no PostgreSQL
Busca semântica entende proximidade de significado, mas pode perder códigos, siglas, nomes próprios e termos exatos.
O PostgreSQL também possui pesquisa textual nativa. Uma busca híbrida executa a recuperação lexical e a vetorial, normaliza ou combina as listas e entrega um conjunto mais equilibrado.
Uma estratégia robusta é ranquear cada lista separadamente e fundi-las por posição, como no Reciprocal Rank Fusion, evitando comparar diretamente escalas de pontuação incompatíveis.
Antes de implementar, entenda as diferenças entre correspondência lexical e busca semântica. A complexidade só se justifica se testes mostrarem ganho em consultas relevantes.
Como avaliar desempenho e qualidade
Latência baixa não compensa resultados irrelevantes. Monte um conjunto de perguntas representativas e registre quais documentos deveriam aparecer.
Execute a busca exata como referência e compare o índice aproximado por recall@k: a proporção dos vizinhos esperados presente nos primeiros k resultados.
- Meça p50, p95 e p99 de latência, não apenas a média.
- Compare qualidade com e sem filtros seletivos.
- Use
EXPLAIN (ANALYZE, BUFFERS)para confirmar o plano executado. - Acompanhe tamanho do índice, tempo de construção e impacto das escritas.
- Teste parâmetros de consulta em uma sessão controlada.
- Repita a avaliação após mudar modelo, chunking ou distribuição dos dados.
O PostgreSQL oferece diferentes tipos de índice, e o planejador pode combinar ou preferir caminhos diferentes conforme estatísticas e filtros.
Portanto, não conclua que um índice está ativo apenas porque ele existe. Observe o plano e avalie sob uma carga semelhante à produção.
Limitações e quando buscar outra solução
Guardar dados operacionais e vetores no mesmo banco simplifica consistência, mas também concentra carga.
Consultas de similaridade intensivas podem disputar CPU, memória e I/O com transações essenciais. Réplicas de leitura, separação de workloads e limites de conexão ajudam, porém aumentam a complexidade operacional.
Considere avaliar uma solução dedicada quando o volume vetorial, a taxa de ingestão ou a concorrência ultrapassarem a capacidade planejada; quando distribuição horizontal e múltiplas regiões forem requisitos centrais; ou quando recursos especializados de filtragem, compressão e gerenciamento forem mais importantes que a integração SQL.
Faça um teste comparável com dados, filtros e métricas reais antes de migrar.
Checklist de implementação
- Confirme versões compatíveis do PostgreSQL e pgvector.
- Defina modelo, dimensão e métrica antes de criar a tabela.
- Registre texto original, fonte, versão e metadados de acesso.
- Comece com busca exata para estabelecer uma referência.
- Crie HNSW ou IVFFlat somente após medir a necessidade.
- Adicione índices convencionais para filtros frequentes.
- Parametrize consultas e aplique autorização no servidor.
- Avalie recall, relevância, latência e custo operacional.
- Planeje reprocessamento ao trocar o modelo de embeddings.
- Monitore crescimento, autovacuum, backups e restauração.
Perguntas frequentes
pgvector transforma PostgreSQL em banco vetorial?
A extensão adiciona tipos, operadores e índices para busca vetorial ao PostgreSQL.
Na prática, ele passa a atender muitos casos de recuperação por similaridade, preservando seus recursos relacionais. Isso não torna sua arquitetura idêntica à de um banco vetorial dedicado.
É preciso normalizar os embeddings?
Depende do modelo e da métrica. Alguns modelos já produzem vetores normalizados; em outros, a normalização é recomendada para produto interno ou comparação por cosseno.
Siga a documentação do modelo e aplique o mesmo processo na indexação e na consulta.
Posso alterar a dimensão de uma coluna vector?
Uma troca de dimensão normalmente acompanha a mudança do modelo e exige gerar novos embeddings.
A abordagem segura é criar uma nova coluna ou tabela, reprocessar os dados, validar a recuperação e então fazer a transição, em vez de misturar representações incompatíveis.
Qual índice escolher: HNSW ou IVFFlat?
HNSW costuma ser o primeiro candidato quando qualidade de recuperação e velocidade de consulta pesam mais, desde que haja memória para isso.
IVFFlat pode ser atraente quando construção e consumo de memória importam mais. Compare ambos com o mesmo conjunto de avaliação.
pgvector funciona com filtros por usuário?
Sim. Use uma coluna de usuário ou conta no WHERE, um índice convencional e, quando apropriado, políticas de segurança em nível de linha.
Teste o recall com o filtro, pois índices aproximados podem precisar explorar mais candidatos.
É possível usar pgvector sem RAG?
Sim. Recomendação de itens, deduplicação, agrupamento, localização de imagens semelhantes e pesquisa semântica são exemplos independentes de geração de texto. RAG é apenas um dos usos mais conhecidos.
Conclusão
O pgvector oferece um caminho direto para incluir embeddings e busca vetorial em aplicações que já confiam no PostgreSQL.
Com poucas instruções SQL, é possível armazenar vetores, consultar similaridade e combinar a recuperação com filtros, joins e controles de acesso.
O resultado de produção, porém, depende de decisões que vão além da extensão: modelo e métrica coerentes, metadados bem definidos, escolha consciente entre busca exata, HNSW e IVFFlat e avaliação contínua de recall e latência.
Comece simples, estabeleça uma referência exata e deixe os dados mostrarem quando otimizar ou separar a arquitetura.