Intermediário 11 minStack

pgvector: a busca vetorial em PostgreSQL

Resposta direta

pgvector é uma extensão open source do PostgreSQL (licença PostgreSQL, permissiva) que adiciona o armazenamento e a busca de vetores a uma base que você já administra, com colunas indexáveis de até 2.000 dimensões (4.000 em meia precisão). Para um corpus local de algumas centenas de milhares de fragmentos, isso significa um serviço a menos para operar e filtros SQL que funcionam, sem uma sincronização a manter com seus dados relacionais.

pgvector é uma extensão do PostgreSQL que adiciona o armazenamento e a busca de vetores a um banco que você já administra. Para a maioria dos projetos de pesquisa documental local, é um serviço a menos para rodar, um backup a menos para organizar e filtros SQL que realmente funcionam — inclusive para os direitos de acesso. O projeto, mantido sob licença PostgreSQL e hospedado no GitHub, contava com mais de 23.000 estrelas no fim de setembro de 2026, na versão 0.8.6, compatível com PostgreSQL 13 e versões mais recentes.

Por Mohamed Meguedmi·Atualização 2026-09-28·Testado no Windows, macOS e Linux

#O argumento: não adicionar um serviço

Uma instalação local para trabalhar com documentos já executa um servidor de modelo, uma etapa de codificação e um sistema de armazenamento de documentos. Adicionar um banco de dados vetorial dedicado significa mais um contêiner, mais uma porta, mais um backup e mais um componente que pode ficar fora de sincronia com seus dados relacionais quando um documento for excluído.

Se o PostgreSQL já está presente — e, em uma aplicação de negócio, quase sempre está —, o pgvector elimina toda essa categoria de problemas. Seus trechos de texto ficam em uma tabela ao lado dos documentos de onde vieram, com chaves estrangeiras que os mantêm consistentes, e uma exclusão se propaga como você espera, sem uma tarefa de limpeza separada para escrever ou monitorar. O projeto também acrescenta busca exata e aproximada, vetores de precisão simples, de meia precisão, binários e esparsos, cinco distâncias (L2, produto escalar, cosseno, L1, Hamming, Jaccard), e herda gratuitamente a conformidade ACID, a recuperação para um instante específico e as junções do PostgreSQL.

#Como funciona na prática

O kit RAG Local

Seus documentos, sua IA: um RAG local confiável para seus PDFs, notas e e-mails — sem enviar nada para a nuvem.

  • Espaço online vitalício
  • PDF + arquivos
  • Atualizações vitalícias

Você armazena uma coluna de vetores ao lado das colunas habituais. Uma consulta ordena as linhas pela distância em relação ao vetor da pergunta e retorna as mais próximas. Três operadores de distância cobrem os casos comuns, e o que você escolher deve corresponder à convenção do modelo de embedding: essa escolha é a causa mais frequente de resultados medíocres que passam despercebidos. Para vetores normalizados com comprimento 1 (o caso dos modelos da OpenAI e da maioria dos modelos de embedding recentes), o produto escalar é o mais rápido de calcular e produz a mesma classificação que o cosseno.

Peças do quebra-cabeça
ElementoO que éO que observar
Coluna de vetorUm array de números de ponto flutuante de dimensão fixaA dimensão vem do modelo de embedding e não muda sem recodificar tudo
Operador de distânciaCosseno, produto escalar ou euclidiano (L2)Deve corresponder ao modelo
Índice HNSWÍndice em grafo, consultas rápidasConstrução lenta e com alto consumo de memória; uma escolha padrão sensata desde a versão 0.5
Índice IVFFlatÍndice por partições, de baixo custo de construçãoCriar quando já houver dados representativos
Nenhum índiceVarredura exata de todas as linhasPlenamente viável até algumas dezenas de milhares de linhas

#O SQL mínimo para começar

  1. 01
    Ativar a extensão
    CREATE EXTENSION IF NOT EXISTS vector; — um único comando, a ser executado uma vez por banco de dados.
  2. 02
    Adicionar a coluna
    ALTER TABLE chunks ADD COLUMN embedding vector(1024); — a dimensão deve corresponder exatamente à do modelo de embedding utilizado.
  3. 03
    Carregar os dados antes de indexar
    Um carregamento em massa via COPY é mais rápido sem um índice existente; crie o índice quando já houver uma quantidade representativa de linhas.
  4. 04
    Criar o índice
    CREATE INDEX CONCURRENTLY ON chunks USING hnsw (embedding vector_cosine_ops); — a opção CONCURRENTLY evita bloquear as operações de escrita durante a construção do índice, que é demorada em uma tabela grande.
  5. 05
    Consultar
    SELECT contenu FROM chunks WHERE document_id IN (SELECT id FROM documents WHERE utilisateur_autorise($1)) ORDER BY embedding <=> $2 LIMIT 5; — filtro de autorização e ordenação por similaridade na mesma consulta.

#Os limites de dimensão, na prática

O pgvector define quatro tipos de colunas, cada um com seu próprio limite de dimensão indexável. O tipo vector padrão (precisão simples, 4 bytes por elemento) é indexável até 2 000 dimensões, o que cobre a maioria dos modelos de embedding open source comuns (384 a 1 024 dimensões). Um modelo mais largo, como o text-embedding-3-large da OpenAI, com 3 072 dimensões por padrão, excede esse limite: a solução documentada é reduzir a dimensão na geração do embedding (a API permite) ou migrar para o tipo halfvec, que armazena em meia precisão (2 bytes por elemento, metade do espaço) e é indexável até 4 000 dimensões. O tipo bit (vetores binários, distâncias de Hamming ou Jaccard) suporta até 64 000 dimensões indexáveis, e o sparsevec (vetores esparsos) até 1 000 elementos não nulos indexados — além disso, o PostgreSQL ainda armazena a coluna (até 16 000 dimensões para vector, halfvec e sparsevec), mas sem poder indexá-la, o que resulta em uma varredura exata.

→
A quantização não é apenas um detalhe de armazenamento
Mudar de vector para halfvec reduz o tamanho de cada linha pela metade, o que permite armazenar mais índices na memória e acelera as consultas em grande escala sem alterar seu modelo de embedding. A quantização binária (tipo bit) vai além: ela compacta o índice para a busca, e depois uma reordenação com base nos vetores completos restaura a precisão perdida — o método documentado pelo próprio projeto para manter um índice volumoso inteiramente na memória, em vez de deixar que parte dele precise ser armazenada em disco.

#Filtragem e permissões de acesso

Uma pergunta real raramente abrange todo o corpus: queremos os trechos desse serviço, posteriores a essa data, nos documentos que esse usuário tem direito de ler. Em uma base vetorial dedicada, é um filtro de metadados com sua sintaxe e seus casos limites. No PostgreSQL, é uma cláusula WHERE junto de uma ordenação por similaridade, com uma junção à sua tabela de usuários, se necessário.

Uma armadilha documentada pelo próprio projeto merece ser conhecida antes de você se deparar com ela em produção: com um índice aproximado (HNSW ou IVFFlat), o filtro é aplicado após a varredura do índice, não antes. Se uma condição retém apenas 10% das linhas e o parâmetro padrão hnsw.ef_search vale 40, apenas 4 linhas em média são retornadas — não as dez solicitadas. A solução oficial, disponível desde a versão 0.8.0, chama-se varredura iterativa do índice (SET hnsw.iterative_scan = strict_order), que repete automaticamente a varredura até encontrar resultados suficientes, em vez de retornar silenciosamente um conjunto truncado.

!
As permissões de acesso não são definidas no prompt
Quando várias pessoas fazem perguntas a um mesmo índice, o filtro de permissões impede que um modelo cite a uma pessoa um documento que ela não deveria ver. Nenhuma instrução de prompt substitui esse filtro, e expressá-lo em SQL com base no seu modelo de autorização existente é muito mais seguro do que reimplementá-lo.

#Onde estão os limites

Memória em grande escala
Milhões de vetores em precisão total ocupam muito espaço; halfvec e a quantização binária reduzem o uso de memória, mas os mecanismos dedicados conseguem comprimir ainda mais de forma nativa. Essa é a diferença mais clara.
Tempo de construção do índice
Construir um índice HNSW em uma tabela muito grande demora e consome muitos recursos; em produção, construí-lo com CREATE INDEX CONCURRENTLY evita bloquear as escritas durante a operação.
A concorrência
Executar buscas vetoriais pesadas junto com sua carga transacional coloca ambas no mesmo servidor. Réplicas de leitura ajudam; separar as funções ajuda ainda mais.
A dimensão dos vetores
Os vetores indexados têm um limite conforme seu tipo (2.000 para vector, 4.000 para halfvec). Os modelos comuns ficam dentro desses limites; um modelo com dimensionalidade muito alta deve ser reduzido ou quantizado.
A pesquisa híbrida
PostgreSQL suporta busca de texto completo (tsvector) e você pode combiná-la com a distância vetorial, mas cabe a você tornar esse processo prático: é necessário executar as duas consultas separadamente e depois fundir as classificações, por exemplo usando fusão de rankings recíprocos (Reciprocal Rank Fusion), em vez de obter uma pontuação híbrida nativa em uma única consulta.
A escalabilidade horizontal
Para ir além de um único servidor, o caminho documentado passa por réplicas de leitura do PostgreSQL ou por uma ferramenta de distribuição como Citus ou PgDog — um componente a mais, contrariando o argumento inicial.
i
O VACUUM em um índice HNSW pode ser lento
A documentação oficial informa explicitamente: a limpeza (VACUUM) de uma tabela cujo índice vetorial usa HNSW pode levar tempo com um grande volume de dados. Para acelerá-la, execute REINDEX INDEX CONCURRENTLY antes do VACUUM, em vez de deixar a operação de manutenção rodar sozinha — um detalhe operacional que poucos tutoriais mencionam antes que a manutenção noturna ultrapasse sua janela.

#pgvector ou uma base dedicada

A pergunta não é qual é objetivamente melhor, mas qual se encaixa na sua situação hoje. O pgvector leva vantagem quando o PostgreSQL já é a fonte de verdade da aplicação: faturamento, contas, documentos-fonte. Um mecanismo dedicado leva vantagem quando o volume de vetores ou a taxa de requisições ultrapassa o que um único servidor transacional consegue absorver sem prejudicar o restante da aplicação, ou quando a equipe prefere isolar o componente de IA do restante do sistema de informação por razões operacionais, em vez de razões puramente ligadas ao desempenho.

Escolher conforme a situação
SituaçãoEscolha
PostgreSQL já em uso, menos de algumas centenas de milhares de trechospgvector, confortavelmente
Os vetores devem permanecer coerentes com dados relacionaispgvector: as transações fazem isso sem custo adicional
Filtragem granular com base nas permissões de acesso existentespgvector
Modelo de embedding com mais de 4.000 dimensões sem possibilidade de reduçãoVerificar o tipo sparsevec ou um banco de dados dedicado pensado para esse caso
Milhões de vetores, muitas consultasUm motor dedicado (Qdrant, Milvus)
Protótipo em um caderno de anotaçõesQualquer um, essa escolha é reversível

#FAQ

O pgvector é rápido o suficiente para RAG?+
Para um corpus local típico — de algumas dezenas de milhares a algumas centenas de milhares de trechos — sim, com um índice HNSW, e muitas vezes até sem índice na parte inferior dessa faixa. A recuperação raramente é a etapa lenta de uma cadeia local: é a geração pelo modelo que domina o tempo de resposta percebido.
pgvector ou Qdrant?+
pgvector se o PostgreSQL já estiver presente e seus dados forem relacionais: menos serviços, consistência transacional, filtros SQL nativos e apenas um backup a organizar. Qdrant quando a escala, a quantização agressiva para reduzir o uso de memória ou um serviço dedicado inteiramente pensado para operações vetoriais forem mais importantes do que a simplicidade de operar um único banco de dados. Ambos atendem bem à mesma necessidade até várias centenas de milhares de vetores.
Qual índice escolher, HNSW ou IVFFlat?+
HNSW como padrão há várias versões: melhor desempenho nas consultas, ao custo de uma construção mais lenta e de maior uso de memória. O IVFFlat custa menos para construir, mas deve ser criado depois que dados representativos já tiverem sido carregados; caso contrário, as partições ficarão mal distribuídas.
Posso filtrar por metadados?+
Sim, em SQL comum, incluindo junções. É uma das melhores razões para escolhê-lo, especialmente para filtrar por permissões de acesso. Atenção, porém: com um índice aproximado, esse filtro é aplicado após a varredura do índice, o que pode retornar menos resultados do que o esperado sem a varredura iterativa.
O que acontece se eu mudar o modelo de embedding?+
Tudo deve ser recodificado: a dimensão e a geometria dos vetores pertencem ao modelo, não ao banco de dados. É um processamento em lotes na GPU, não uma migração de esquema, e é necessário recriar a coluna se a nova dimensão ultrapassar a declarada. Planeje uma janela de transição, pois o índice antigo permanece válido enquanto a recodificação não estiver concluída.
Meu modelo de embedding tem mais de 2.000 dimensões, o que fazer?+
O tipo vector padrão indexa até 2.000 dimensões. Acima disso, use o tipo halfvec (até 4.000, em meia precisão) ou reduza a dimensão durante a geração, se o seu fornecedor permitir, como a OpenAI oferece para text-embedding-3-large. Sem índice, o PostgreSQL ainda armazena até 16.000 dimensões, mas com varredura exata.
Como diagnosticar uma consulta vetorial lenta?+
A documentação recomenda EXPLAIN (ANALYZE, BUFFERS) antes da consulta para verificar se o índice realmente é usado e quantos blocos são lidos. Uma consulta exata sem índice melhora com o aumento de max_parallel_workers_per_gather; uma consulta aproximada lenta aponta frequentemente para um índice ainda em construção ou para falta de memória para mantê-lo em cache.
Este guia ajudou você?

Um comentário, um erro ou uma observação? Avise-nos; isso ajuda a melhorar o guia para todos.