O caso contra o pgvector
(alex-jacobs.com)- A extensão pgvector do Postgres oferece suporte à busca por similaridade vetorial, mas existe uma grande diferença entre o nível de demo e o ambiente real de produção
- Tanto os índices IVFFlat quanto HNSW têm vantagens e desvantagens bem definidas; em especial, o HNSW traz como problema o uso de vários GB de memória na criação do índice e o longo tempo de build
- A busca em tempo real e a atualização de índices são estruturalmente difíceis e, com inserções e atualizações contínuas, surgem contenção de locks e degradação de desempenho
- Devido à estratégia de filtragem (Pre/Post) e às limitações do query planner, aparece um equilíbrio instável entre precisão da busca e velocidade
- É preciso implementar manualmente recursos oferecidos por bancos de dados vetoriais dedicados (Pinecone, Weaviate etc.), o que no fim leva a maior complexidade operacional e aumento de custos
Visão geral das limitações do pgvector
- O pgvector é uma extensão que adiciona busca por similaridade vetorial ao Postgres e funciona bem em demos simples, mas em ambientes de produção surgem problemas de escalabilidade
- Muitos posts de blog tratam apenas da instalação e de exemplos simples de consulta, e quase não mencionam os problemas de desempenho, memória e gerenciamento de índices que aparecem em produção
O problema da escolha do índice
- O pgvector oferece dois tipos de índice: IVFFlat e HNSW
- IVFFlat: estrutura baseada em clusters; a criação do índice é rápida, mas a configuração do número de clusters afeta fortemente o desempenho e a precisão
- Como a redistribuição de clusters não é possível, é necessário reconstruir o índice periodicamente
- HNSW: estrutura de grafo multicamada que oferece precisão e desempenho consistente, mas tem uso de memória muito alto e velocidade lenta na criação do índice
- IVFFlat: estrutura baseada em clusters; a criação do índice é rápida, mas a configuração do número de clusters afeta fortemente o desempenho e a precisão
- Ao criar índices para milhões de vetores, pode haver uso de mais de 10 GB de RAM, o que representa uma ameaça direta à estabilidade do banco de dados em produção
As dificuldades da busca em tempo real
- Novos dados precisam ficar pesquisáveis imediatamente após a inserção, mas, por causa da própria estrutura de atualização dos índices, é difícil refletir isso em tempo real
- IVFFlat: novos vetores são adicionados aos clusters existentes e, com o tempo, ocorre desequilíbrio entre clusters → necessidade de rebuild periódico
- HNSW: durante a inserção, a atualização do grafo causa contenção de locks e carga de memória
- Durante a reconstrução do índice, é difícil manter a consistência dos dados e garantir a continuidade do serviço
- Em ambientes de produção, são necessárias várias estratégias de contorno, como staging tables, índices duplos, build offline e eventual consistency
Limitações da filtragem e do query planner
- Ao combinar filtragem de metadados como
status,user_id,categorycom busca vetorial, a escolha entre Pre-filter vs Post-filter tem grande impacto no desempenho- Pre-filter favorece filtros seletivos, mas pode ser lento quando há muitos dados
- Post-filter é rápido, mas existe a possibilidade de perda de resultados após a filtragem
- O query planner do Postgres não entende o modelo de custo da similaridade vetorial, e como as estatísticas são imprecisas, acaba gerando planos de execução ineficientes
- Como resultado, tornam-se necessárias soluções paliativas como CTE, particionamento e reescrita de queries, o que é ineficiente em escala
Comparação com bancos de dados vetoriais dedicados
- Pinecone, Weaviate, OpenSearch k-NN e outros oferecem por padrão seleção automática da estratégia de filtragem, busca híbrida, indexação em tempo real e escalabilidade horizontal
- No pgvector, esses recursos precisam ser implementados manualmente, o que leva a complexidade operacional e maior carga de manutenção
- O pgvectorscale da Timescale oferece StreamingDiskANN, build incremental de índice e melhorias de filtragem, mas
- não é suportado no AWS RDS e ainda existe a carga adicional de instalar e gerenciar outra extensão
Custos e considerações operacionais
- Bancos vetoriais dedicados são serviços pagos, mas ao considerar overprovisioning da infraestrutura Postgres, gerenciamento de índices e tempo de engenharia, eles podem na prática sair mais baratos
- Como exemplo, o Turbopuffer começa em US$ 64 por mês e oferece simplicidade operacional e escalabilidade
Conclusão e recomendações
- O pgvector é tecnicamente excelente, mas tem muitas restrições em ambientes de produção
- Pontos principais a considerar ao construir um sistema em produção
- A complexidade do gerenciamento de índices e a alta exigência de memória
- As limitações do query planner, que levam à ineficiência na filtragem
- O custo da indexação em tempo real e a perda de qualidade
- A simplificação excessiva dos posts de blog
- A razão de existir dos bancos de dados vetoriais dedicados e sua eficiência
- Em conclusão, a complexidade operacional é maior do que a simplicidade da integração com Postgres, e para a maioria das equipes usar um banco de dados vetorial dedicado é a escolha mais realista
5 comentários
Ainda assim, para consultas compostas (embedding + SQL tradicional), não tem nada melhor que o
pg_vector.Acho que, para o ecossistema ficar saudável, também precisa haver muitas refutações a essas narrativas de solução universal.
Concordo. Para organizações que já usavam bem o Postgres e estão começando com VectorDB em pequena escala, o pgVector é claramente uma ótima opção, mas parece que, quando o tráfego aumenta — especialmente o tráfego de escrita —, os problemas mencionados pelo autor do texto original acabam se tornando um gargalo.
Isso mesmo. Afinal, nada é perfeito. Acho que tudo bem dizer algo como "há outras questões mais urgentes", mas não se deve tolerar a ideia de que "o nível atual já é suficiente".
Comentário no Hacker News
Nós, da Discourse, já usamos pgvector em produção em milhares de bancos de dados
Ele é usado na maioria das visualizações de página, e o recurso Iterative Scans foi adicionado na versão 0.8.0 para melhorar os problemas de pré/pós-filtragem
Para um serviço único, um banco de dados vetorial dedicado pode até ser mais fácil, mas isso não é uma solução universal
Para armazenamento usamos halfvec (float de 16 bits) e, para índices, bit (vetores binários), garantindo tanto custo de armazenamento quanto desempenho
Usamos o Vespa para fazer buscas em estilo map-reduce no nível dos nós
Para fazer algo parecido no Postgres, provavelmente seriam necessários sharding e lógica de aplicação complexa
Acho que reindexação ou desnormalização de metadados inevitavelmente levariam muito tempo
Ainda assim, banco de dados vetorial não é solução para tudo, e sistemas como o Vespa, que suportam filtragem relacional, são muito mais eficientes
Mas o iterative scan não é uma solução fundamental, e sim algo mais próximo de um paliativo
É preciso entender parâmetros como ef_search e max_search_tuples, e o planner não compreende totalmente o modelo de custo da busca vetorial com filtragem
No fim, a questão é se você tem capacidade para ajustar manualmente um planejador de consultas inteligente ou se vai usar um serviço especializado nisso
O método descrito neste artigo da Microsoft foi implementado pelo Timescale no pgvectorscale
Esse método pode ser mais eficiente do que uma simples pré/pós-filtragem
Nós resolvemos a maior parte dos problemas do pgvector mencionados no post com o VectorChord
Usando IVF + quantization, ele oferece atualizações 15 vezes mais rápidas do que o HNSW do pgvector
Com 16 vCPU e 32 GB de memória, é possível indexar 100 milhões de vetores de 768 dimensões em 20 minutos
É possível reindexar sem perda de dados com
CREATE INDEX CONCURRENTLYTambém oferece suporte a pré/pós-filtragem e busca híbrida baseada em BM25
Para mais detalhes, veja o blog do VectorChord
O caso pode ser visto neste blog
A construção de índice consome muita memória, mas isso pode ser controlado com
maintenance_work_memA reconstrução do índice pode ser feita com
REINDEX CONCURRENTLY, e atualizar HNSW é conceitualmente parecido com atualizar uma B+treeEste texto dá a impressão de que não leu a documentação do Postgres direito
maintenance_work_memdeixa a indexação mais lentaB+tree mexe apenas em páginas log H, enquanto HNSW precisa modificar milhares de vetores
Para reconstruí-lo, é preciso garantir mais que o dobro da capacidade do banco, e isso também afeta outras cargas de trabalho
REINDEX CONCURRENTLYtambém leva muito tempoMesmo que a complexidade de inserção no HNSW seja baixa, o custo constante é alto, então na prática isso pesa bastante
maintenance_work_mem, ocupar vários GB de RAM por horas em produção é arriscadoREINDEX CONCURRENTLYtambém usa de 2 a 3 vezes mais disco e afeta o desempenhoNo fim, o problema central não é falta de recursos no Postgres, e sim a complexidade operacional
Bancos de dados vetoriais dedicados lidam com isso automaticamente, então para equipes pequenas eles são bem mais eficientes
O fato de o Turbopuffer começar em US$ 64 por mês ajuda a explicar a popularidade do pgvector
Se US$ 64 parecer caro, use pgvector; se parecer barato, então seu caso de uso já é complexo o bastante para um banco de dados vetorial dedicado fazer mais sentido
Também vi muitos clientes do GCP usando pgvector HNSW em produção
Mas isso só é realista na faixa de 0 a 10 milhões de vetores
É preciso considerar ETL, sobrecarga operacional, problemas de consistência etc.
Se você precisa de transações, busca híbrida e baixa latência, AlloyDB + ScaNN é uma escolha melhor
(Aliás, eu criei o ScaNN no GCP e hoje lidero o AlloyDB Semantic Search)
Meu princípio básico é YAGNI
Reduzo ao máximo a quantidade de serviços e, se surgir um problema, só então adiciono algo novo
Se o Postgres for suficiente, sigo com ele; se não for, aí passo a saber exatamente do que preciso
Coisas como gravação vetorial em tempo real e combinação de filtros SQL com busca por similaridade parecem detalhes, mas na prática são recursos essenciais
Quando a escala cresce, essas limitações aparecem de forma crítica
Ao usar modelos de embedding vetorial, há bastante utilidade mesmo sem datasets enormes
Por exemplo, em casos como busca de documentos ou busca de informações de produtos
Eu queria uma interface em que, ao gravar documentos como em um sistema de arquivos, o índice fosse atualizado automaticamente
Por isso serviços como Amazon S3 Vectors(link) parecem interessantes
Tenho curiosidade sobre experiências reais de uso
Veja este artigo para um tutorial relacionado
Os problemas mencionados já foram resolvidos, e eu prefiro usar PGVector
Se o Postgres consegue substituir o Kafka e lidar com 100 mil eventos por segundo, então o PGVector também dá conta no lugar de um banco vetorial dedicado como o Chroma
Link de referência
A maioria dos casos de uso de pgvector é de datasets pequenos, como “chatbot baseado em documentação técnica”
Os dados não mudam com frequência e não há multitenancy, então há menos problemas de filtragem
Já o Chroma suporta SPANN, SPFresh, busca híbrida e é totalmente open source sob Apache 2.0
Com cobrança por uso, dá para usar por cerca de US$ 1 por mês
O Redis Vector Sets, que desenvolvi ao longo do último ano, resolve esses problemas
Implementamos HNSW diretamente, permitindo atualizações em tempo real, e a memória é recuperada imediatamente ao excluir
Suporta inserções de centenas de milhares de ops/sec e buscas de 50 mil ops/sec
Também suporta quantization por padrão, o que melhora a eficiência de memória
Tudo está explicado em detalhes no README
No momento, a funcionalidade de replicação também já foi totalmente testada