Para até um milhão de vetores com transações ACID, o PostgreSQL com a extensão pgvector é a escolha ideal. Ele oferece menor custo e reaproveita o banco existente.
Quando a base supera um milhão de vetores e exige latência submilissegundo em p99, o Qdrant em Rust torna-se necessário.
Para hiperescala multi-tenant acima de 50 milhões de vetores, o Milvus atua como arquitetura desacoplada padrão. Ele separa computação e armazenamento sobre Kubernetes e S3.

Quando o PostgreSQL com pgvector atende sua aplicação de IA?
O pgvector atende com excelência sistemas com menos de um milhão de vetores e volume moderado de consultas simultâneas.
A maior vantagem é operacional. Governança ACID, políticas de backup e JOINs relacionais do ecossistema PostgreSQL continuam diretamente disponíveis.
Entretanto, a arquitetura relacional impõe limites físicos para vetores densos. O PostgreSQL organiza tabelas em páginas fixas de 8 KB.
Um vetor de 1536 dimensões em FP32 ocupa 1536 × 4 bytes = 6.144 bytes. Com cabeçalhos, a tupla excede 2 KB.
Esse tamanho aciona o mecanismo TOAST do PostgreSQL. O banco fatia o vetor em fragmentos secundários, elevando leituras aleatórias em disco.
Além do TOAST, o controle de concorrência multiversão (MVCC) causa atrito com o grafo HNSW. Atualizações em metadados geram versões mortas de linhas.
O autovacuum limpa linhas mortas, mas não reconstrói o grafo vetorial. Suas arestas apontam para registros obsoletos.
Essa fragmentação degrada a precisão de busca (Recall@K), exigindo rotinas periódicas de REINDEX TABLE CONCURRENTLY.
A memória também exige atenção. O pgvector divide o shared_buffers com tabelas relacionais e índices B-Tree, gerando competição por espaço na DRAM.
-- Configuração de índice HNSW com pgvector no PostgreSQL
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE documentos_corporativos (
id BIGSERIAL PRIMARY KEY,
conteudo TEXT NOT NULL,
categoria VARCHAR(64) NOT NULL,
embedding vector(1536)
);
-- Parâmetros m e ef_construction controlam o grafo
CREATE INDEX idx_documentos_hnsw ON documentos_corporativos
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 128);
-- Ajuste de profundidade na consulta
SET hnsw.ef_search = 64;
SET hnsw.iterative_scan = relaxed_order;
Como o Qdrant atinge latência submilissegundo em Rust?
O Qdrant atinge latência submilissegundo em p99 através de motor nativo em Rust com armazenamento segmentado, concorrência lock-free e indexação com metadados integrados.
Projetado exclusivamente para busca vetorial, o Qdrant elimina custos de interpretadores. Sua arquitetura divide coleções em shards formados por segmentos independentes.
Segmentos de ingestão recebem escritas imediatas em modo append-only na memória sem construir grafos complexos na entrada.
Em segundo plano, o otimizador do Qdrant consolida os segmentos preenchidos em blocos selados. Ele constrói o grafo HNSW definitivo e calcula matrizes quantizadas.
Essa estrutura elimina a fragmentação típica do MVCC. Registros excluídos são removidos durante a mesclagem periódica de segmentos, preservando o grafo intacto.
O Qdrant também oferece persistência híbrida. Vetores originais em FP32 podem ficar mapeados em disco NVMe via mmap(), liberando DRAM para tarefas críticas.
Enquanto vetores densos residem em disco, as representações quantizadas e o grafo HNSW permanecem na RAM. Essa divisão reduz a memória em até 70%.
A concorrência em Rust emprega estruturas atômicas sem travas globais. Múltiplas threads navegam pelos segmentos em paralelo com alta eficiência de CPU.
A comunicação padrão utiliza gRPC e Protocol Buffers. O formato binário reduz tráfego de rede e evita processamento pesado de JSON.
Quando a escala de dados exige a arquitetura desacoplada do Milvus?
O Milvus torna-se mandatório quando a coleção supera 50 milhões de vetores e a infraestrutura exige separação estrita entre escrita, consulta e armazenamento.
Desenhado sob princípios cloud-native, o Milvus desacopla computação sem estado da camada persistente. Ele delega a durabilidade para buckets S3 ou MinIO.
Proxies stateless recebem requisições gRPC, distribuem as buscas para nós de consulta e consolidam o ranqueamento top-K.
A ingestão contínua passa por um barramento como Apache Kafka ou Apache Pulsar. O barramento atua como Write-Ahead Log distribuído garantindo tolerância a falhas.
Nós de dados (Data Nodes) consomem mensagens e formam segmentos temporários. Ao atingir o limite, salvam arquivos Parquet no armazenamento de objetos.
A indexação ocorre em nós especializados (Index Nodes). Eles geram índices HNSW ou DiskANN de forma isolada, sem interferir nos servidores de consulta.
Os nós de consulta (Query Nodes) mantêm apenas os índices ativos na RAM. Eles executam a busca através do motor Knowhere em C++.
O Knowhere utiliza rotinas vetorizadas AVX-512 e AVX2 em assembly, suportando também aceleração direta por GPUs corporativas.
Essa arquitetura viabiliza elasticidade independente. Picos de escrita escalam nós de dados, enquanto aumentos de consulta escalam nós de leitura.
A contrapartida é o esforço operacional. Manter etcd, brokers de mensagens, MinIO e pods distribuídos exige equipe experiente em Kubernetes.
HNSW vs. IVFFlat vs. DiskANN: qual algoritmo de indexação escolher?
O algoritmo HNSW é a melhor opção para precisão máxima e baixa latência em memória, enquanto DiskANN viabiliza bilhões de vetores em discos SSD NVMe.
A busca exata compara a consulta contra toda a base. Para dez milhões de vetores de 1536 dimensões, são 15 bilhões de cálculos.
Algoritmos de busca aproximada (ANN) negociam frações mínimas de precisão para entregar respostas em milissegundos.
O algoritmo HNSW, formalizado por Malkov e Yashunin (2018), cria uma rede geométrica inspirada em skip-lists multidimensionais.
O grafo organiza pontos em camadas. Níveis superiores possuem arestas longas, enquanto a base contém todos os vetores densamente conectados.
A busca começa na camada mais alta com navegação gulosa. Ao atingir o melhor nó local, o algoritmo desce de camada e refina a busca.
O HNSW é configurado por três parâmetros centrais:
M: número máximo de arestas bidirecionais por nó;ef_construction: tamanho da lista de candidatos durante a montagem do índice;ef_search: tamanho da fila dinâmica de busca na consulta.
A pegada de memória do HNSW em FP32 segue a fórmula:
RAM_HNSW ≈ N × (d × 4 bytes) + N × (M × 2 × 4 bytes) + Overhead_Nó
Para um milhão de vetores de 1536 dimensões com M = 16, a memória pura varia entre 7,5 GB e 8,5 GB.
O IVFFlat usa particionamento Voronoi com clustering k-means. Ele divide o espaço em células e examina apenas as listas invertidas vizinhas.
Embora o IVFFlat seja leve em memória e rápido para indexar, ele sofre em alta dimensionalidade. Acima de 768 dimensões, o recall sofre perda drástica.
Em bases gigantescas, o DiskANN (NeurIPS 2019) grava o grafo Vamana em SSDs via io_uring.
Um índice compacto reside na RAM, enquanto vetores completos são lidos do SSD em paralelo, viabilizando bilhões de pontos por nó.
Como a quantização escalar e binária reduz a pegada de RAM em até 32×?
A quantização converte coordenadas vetoriais de 32 bits em inteiros discretos ou bits únicos, reduzindo a memória em até 32 vezes com suporte em hardware.
Manter tensores FP32 na memória encarece a infraestrutura. Técnicas de quantização comprimem vetores explorando simetrias dimensionais.

A Quantização Escalar de 8 bits (SQ8) mapeia cada dimensão contínua para um inteiro entre 0 e 255 via escala linear min-max.
Cada dimensão cai para um byte. Um milhão de vetores de 1536 dimensões diminui de 6,14 GB para 1,53 GB.
CPUs com AVX-512 VNNI usam a instrução VPDPBUSD, calculando múltiplos produtos escalares por ciclo e acelerando a busca em até 3 vezes.
Em modelos de embedding consolidados, a perda de precisão Recall@10 com SQ8 é menor que 2%. Isso torna o SQ8 o padrão recomendado para produção.
A Quantização Binária (BQ ou 1-bit) leva a compressão ao extremo ao representar cada dimensão por um único bit baseado no sinal:
b_i = 1 se x_i > 0, senão 0
Um vetor de 1536 dimensões é compactado para 192 bytes. Um milhão de vetores passa a ocupar apenas 192 MB em memória, atingindo redução de 32 vezes.
O cálculo de similaridade binária torna-se proporcional à distância de Hamming. A operação é executada com duas instruções de hardware: XOR e POPCNT.
Instruções vetoriais modernas processam centenas de dimensões por ciclo, acelerando a busca em até 20 a 40 vezes vs. FP32.
A busca em BQ utiliza rescoring em dois estágios: travessia rápida na RAM e recálculo exato de distâncias no disco.
O procedimento entrega mais de 96% de recall final quando embeddings possuem mais de mil dimensões com distribuição centrada, como modelos OpenAI e Cohere.
Como resolver filtragem de metadados sem colapso de recall?
A filtragem em estágio único avalia predicados relacionais durante a travessia do grafo HNSW, evitando o colapso do pós-filtro e a lentidão do pré-filtro.
Consultas reais quase sempre exigem filtros conjuntos, como buscar documentos de certo departamento criados após determinada data.
A forma como o motor vetorial combina a distância matemática com filtros booleanos determina a estabilidade da latência.
No modelo de pós-filtragem (post-filtering), o grafo busca vizinhos globais e aplica o filtro booleano no resultado final.
Se o filtro cobrir 1% da base, os vizinhos raramente atenderão à condição, retornando resultados vazios ou incompletos.
Na pré-filtragem linear (pre-filtering), o banco filtra IDs válidos e compara vetores por força bruta.
Se o filtro cobrir muitas linhas, o grafo HNSW é ignorado. O scan linear eleva a latência para centenas de milissegundos.

Os motores modernos superam esse problema integrando o filtro na travessia geométrica (in-graph filtering).
No Qdrant, o algoritmo ACORN usa nós inválidos como pontes de navegação: o grafo avança sem travar e ranqueia apenas nós válidos.
No Milvus, o motor Knowhere cria máscaras de bits (bitsets) para predicados escalares. Instruções SIMD mascaram vetores inválidos dentro do loop de distância.
No pgvector 0.8+, o scan iterativo de índice expande a busca no grafo. Ele continua até encontrar a quantidade solicitada de registros válidos.
Comparativo estruturado: benchmarks e métricas em 1 milhão de vetores
Métricas avaliadas sob carga de 1 milhão de vetores de 1536 dimensões. O ambiente utiliza servidores dedicados com 16 vCPUs e 64 GB de RAM.
Os dados sintetizam medições do VectorDBBench e ANN-Benchmarks comparando consumo de memória e vazão por nó.
| Parâmetro Técnico | pgvector (PostgreSQL 17+) | Qdrant (v1.18+ em Rust) | Milvus (v2.4+ Knowhere) |
|---|---|---|---|
| Linguagem do Core | C (Extensão nativa Postgres) | Rust (Motor vetorial standalone) | Go (Coordenação) e C++ (Cálculo) |
| Arquitetura | Monolítica Relacional | Standalone ou Cluster Sharded | Distribuída Desacoplada Cloud-Native |
| Persistência Base | Páginas Heap e TOAST em disco | Segmentos selados no disco | Arquivos Parquet em S3 ou MinIO |
| Algoritmos ANN | HNSW, IVFFlat | HNSW com ACORN, Payload-aware | HNSW, IVFFlat, DiskANN, SCANN |
| Técnicas de Quantização | BQ (bit), FP16 (halfvec) | SQ8, BQ 1-bit / 2-bit, TurboQuant | SQ8, BQ, PQ, FP16, BF16 |
| Consumo de RAM (1M vetores) | ~7,5 GB a 9,0 GB (FP32) | ~2,5 GB (SQ8) / ~1,2 GB (BQ+mmap) | ~3,0 GB (SQ8) / ~8,5 GB (FP32) |
| Vazão Média (QPS por nó) | 150 a 450 QPS | 2.000 a 5.500+ QPS | 1.800 a 4.800 QPS (Query Node) |
| Latência p99 (1M vetores) | 12 ms a 45 ms (com picos sob carga) | 1,2 ms a 4,5 ms (estável) | 3,5 ms a 9,0 ms (estável) |
| Filtragem de Metadados | Iterative Index Scan (v0.8+) | Payload-aware HNSW nativo | Bitset Masking em loop SIMD |
| Impacto de Updates | Alto (Linhas mortas e bloat) | Desprezível (Compactação em fundo) | Desprezível (LSM-tree merge) |
| Esforço de Operação | Mínimo (PostgreSQL existente) | Baixo a Médio (Binário único) | Elevado (etcd, Kafka, MinIO, K8s) |
| Perfil Ideal | Aplicações integradas a CRUD ACID | Baixa latência e filtros dinâmicos | Bases multi-tenant hiperdimensionais |
Framework de decisão: qual banco vetorial adotar na sua infraestrutura?
A decisão entre pgvector, Qdrant e Milvus deve considerar o volume total de vetores, taxa de consultas concorrentes e equipe disponível.
Soluções distribuídas não devem ser introduzidas prematuramente. Porém, insistir no PostgreSQL para dezenas de milhões de vetores compromete a performance.
Cenário 1: Permaneça no pgvector
Adote o pgvector se sua arquitetura já utiliza PostgreSQL e atende a estes requisitos:
- Base de dados com menos de um milhão de vetores;
- Volume inferior a duzentas consultas concorrentes por segundo;
- Necessidade de integridade ACID estrita com entidades relacionais;
- Consultas dependentes de
JOINscom tabelas corporativas; - Equipe focada em produto sem especialistas em bancos distribuídos.
Cenário 2: Migre para o Qdrant
Evolua para o Qdrant quando a aplicação atingir as seguintes demandas técnicas:
- Coleções entre um milhão e cinquenta milhões de vetores;
- Exigência de latência submilissegundo em p99 sob alto tráfego;
- Filtros dinâmicos complexos aplicados em tempo real sem perda de precisão;
- Otimização de memória via quantização escalar (SQ8) ou binária (BQ) com
mmap; - Preferência por binário único em Rust com deploy via Docker ou Raft nativo.
Cenário 3: Escale com o Milvus
Implemente o Milvus quando o escopo exigir arquitetura distribuída de hiperescala:
- Coleções acima de 50 a 100 milhões de vetores com projeção para bilhões;
- Necessidade de isolar completamente nós de ingestão de nós de busca;
- Armazenamento em data lakes de baixo custo sobre buckets S3 ou MinIO;
- Infraestrutura corporativa baseada em Kubernetes e mensageria distribuída;
- Demanda por indexação acelerada em GPU para processamento em lote.
Perguntas Frequentes sobre Bancos de Dados Vetoriais
O pgvector é rápido o suficiente para sistemas de busca em produção?
Sim, o pgvector é confiável para coleções de até um milhão de vetores. Ele entrega latências entre 10 ms e 30 ms quando a memória comporta o grafo HNSW. Para volumes maiores ou alta concorrência, motores dedicados tornam-se indispensáveis.
Vale a pena utilizar quantização escalar SQ8 em coleções corporativas?
Sim, a quantização escalar SQ8 é amplamente recomendada para a maioria das aplicações em produção. Ela reduz o consumo de memória RAM em 75% e acelera o cálculo de distâncias via instruções SIMD da CPU. A perda de precisão de busca em modelos densos é marginal e quase imperceptível.
Qual a diferença fundamental entre Qdrant e Milvus na prática?
O Qdrant é um motor vetorial integrado em Rust com foco em baixa latência por nó e facilidade de manutenção. O Milvus é uma plataforma distribuída que desacopla ingestão, computação e armazenamento em nuvem. O Qdrant é ideal para média e alta escala ágil, enquanto o Milvus atende ambientes de hiperescala multi-tenant.
Por que a filtragem por metadados é um ponto crítico em bancos vetoriais?
A filtragem pós-busca pode descartar todos os vizinhos se o filtro for restritivo, gerando listas vazias. Motores modernos filtram durante a navegação do grafo HNSW, garantindo precisão total sem degradar a latência da consulta.
É possível rodar bancos vetoriais dedicados em servidores com pouca memória RAM?
Sim, motores como o Qdrant suportam vetores em disco com mmap e índices quantizados na RAM. Essa configuração permite que máquinas com 16 GB de RAM atendam milhões de vetores com estabilidade.