O time de ML acabou de te pedir um “vector database” em produção. Você sabe operar PostgreSQL, Redis, Cosmos DB. Mas isso? É um banco de dados ou um índice de busca? Precisa de backup? Tem replicação? Qual o modelo de consistência?
Aqui dentro: o que é, como funciona por dentro, e como operar em produção.
tl;dr: vector database, na prática, é um motor de busca por similaridade com índice ANN. O custo mora em RAM, recall, rebuild de índice e operação de busca, não só em “guardar vetores”.
O mapa pro profissional de infra
| Conceito Vector DB | O que faz | Equivalente em infra |
|---|---|---|
| Vector/Embedding | Array de floats que representa significado | Uma row com 1536 colunas numéricas |
| Similarity search | Buscar vetores parecidos | Query com ORDER BY distance LIMIT K |
| Index (HNSW, IVF) | Estrutura pra busca rápida | B-tree, hash index num banco relacional |
| Dimension | Tamanho do vetor (768, 1536, 3072) | Largura da row (quantas colunas) |
| Distance metric | Como calcular “parecido” | Cosine similarity, Euclidean, dot product |
| Recall | % de resultados corretos encontrados | Taxa de acerto da recuperação (o que deveria aparecer apareceu?) |
O problema fundamental
Num banco relacional, buscar é comparar valores exatos ou ranges. WHERE status = 'active' ou WHERE created_at > '2024-01-01'. Indexes como B-tree resolvem isso em O(log n).
Com vetores, o problema é diferente. Você tem um vetor de query (1536 floats) e precisa encontrar os K vetores mais similares entre milhões. A busca “exata” (comparar com todos) é O(n). Com 10 milhões de documentos, cada busca compara 10 milhões de vetores. Inaceitável.
A solução? Approximate Nearest Neighbor (ANN). Aceitar 95-99% de recall em troca de velocidade 1000x maior. É o mesmo trade-off que caching: você abre mão da busca exata em troca de resultado rápido o suficiente.
HNSW: o algoritmo que você vai encontrar em todo lugar
Hierarchical Navigable Small World (HNSW) é o índice mais usado. Pensa nele como um skip list multi-dimensional.
A ideia:
Cada nível é um grafo com conexões entre vetores. Níveis superiores têm poucos nós e conexões longas. Níveis inferiores concentram mais nós e vizinhos próximos.
Busca: começa no topo (poucos saltos longos pra chegar na região certa), desce nível por nível refinando. É como pegar a via expressa até o bairro e depois entrar nas ruas locais.
Performance:
- Tempo de busca: em muitos workloads, perto de O(log n)
- Memória: aproximadamente O(n × d) pros vetores + O(n × M) pro grafo
- Build time: cresce algo como O(n × log n)
HNSW em números reais
| Vetores | Dimensão | Memória (HNSW) | Latência p99 | Recall@10 |
|---|---|---|---|---|
| 1M | 1536 | ~8 GB | poucos ms | 98% |
| 10M | 1536 | ~80 GB | dezenas baixas de ms | 97% |
| 100M | 1536 | ~800 GB | dezenas de ms | 95% |
Isso é ordem de grandeza com float32 e sem compressão agressiva. O número exato depende de M, efSearch, hardware e de o índice caber ou não em memória.
Percebe o padrão? HNSW gosta de RAM. 100M vetores de 1536 dimensões podem passar fácil de centenas de GB. É por isso que vector databases em escala ficam caros rápido.
IVF: a alternativa mais amigável pra disco
Inverted File Index (IVF) usa uma abordagem diferente. Em vez de grafo, ele particiona o espaço em clusters.
- Training: roda K-means pra dividir os vetores em N clusters (ex: 1024)
- Busca: identifica os clusters mais próximos da query, busca apenas dentro deles
Trade-off: IVF é mais eficiente em disco, mas o parâmetro nprobe (quantos clusters buscar) controla o trade-off recall vs velocidade. Menos probes = mais rápido, menos preciso.
Quantização: comprimindo vetores
Se HNSW precisa de muita RAM, quantização reduz isso drasticamente. Em vez de guardar cada dimensão como float32 (4 bytes), comprime pra menos bits.
| Tipo | Bytes por dimensão | Vetor 1536d | Perda de accuracy |
|---|---|---|---|
| Float32 (original) | 4 | 6.1 KB | 0% |
| Float16 | 2 | 3.0 KB | ~0% |
| Int8 (SQ) | 1 | 1.5 KB | 1-3% |
| Binary (1 bit) | 0.125 | 192 bytes | 10-20% |
| Product Quantization | ~0.25-0.5 | 384-768 bytes | 3-8% |
Na prática, Scalar Quantization (int8) dá o melhor custo-benefício. Reduz RAM em 4x com perda mínima de accuracy.
# Azure AI Search: criar índice vetorial com quantização via REST data plane
az rest --method POST \
--url "https://meu-search.search.windows.net/indexes?api-version=2026-04-01" \
--skip-authorization-header \
--headers Content-Type=application/json api-key=$SEARCH_ADMIN_KEY \
--body '{
"name": "meu-indice",
"fields": [
{"name": "id", "type": "Edm.String", "key": true, "filterable": true},
{"name": "content", "type": "Edm.String", "searchable": true},
{
"name": "embedding",
"type": "Collection(Edm.Single)",
"searchable": true,
"retrievable": false,
"stored": false,
"dimensions": 1536,
"vectorSearchProfile": "meu-perfil"
}
],
"vectorSearch": {
"algorithms": [{
"name": "meu-hnsw",
"kind": "hnsw",
"hnswParameters": {
"m": 4,
"efConstruction": 400,
"efSearch": 500,
"metric": "cosine"
}
}],
"compressions": [{
"name": "minha-quantizacao",
"kind": "scalarQuantization",
"scalarQuantizationParameters": {
"quantizedDataType": "int8"
},
"rescoringOptions": {
"enableRescoring": true,
"defaultOversampling": 10,
"rescoreStorageMethod": "preserveOriginals"
}
}],
"profiles": [{
"name": "meu-perfil",
"algorithm": "meu-hnsw",
"compression": "minha-quantizacao"
}]
}
}'
O bloco rescoringOptions é importante. Busca primeiro com vetores quantizados (rápido), depois recalcula o ranking com vetores originais (preciso). É como usar um CDN pra filtrar e depois ir no origin server pra confirmar.
Comparando soluções: o que usar
| Solução | Tipo | Melhor pra | Cuidado com |
|---|---|---|---|
| Azure AI Search | Managed, hybrid (vector + text) | RAG com docs, busca semântica | Custo em escala alta |
| pgvector (PostgreSQL) | Extension em DB existente | Times pequenos, já usam PostgreSQL | Escala de alguns milhões pra cima exige cuidado |
| Qdrant | Dedicado, open-source | Alta performance, self-hosted | Ops overhead |
| Pinecone | Managed, serverless | Escala sem ops | Vendor lock-in, custo |
| Azure Cosmos DB (vector) | Multi-model managed | Já usa Cosmos, quer adicionar vectors | Feature mais recente |
| Redis (vector) | In-memory, rápido | Latência ultra-baixa, cache de embeddings | RAM cara em escala |
pgvector: quando já tem PostgreSQL
Se seu time já roda PostgreSQL, pgvector é a forma mais simples de começar. Adiciona suporte a vetores sem novo serviço.
-- Habilitar extensão
CREATE EXTENSION vector;
-- Criar tabela com coluna de embedding
CREATE TABLE documentos (
id SERIAL PRIMARY KEY,
conteudo TEXT,
embedding vector(1536)
);
-- Criar índice HNSW
CREATE INDEX ON documentos
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- Buscar os 5 mais similares via prepared statement / driver
-- Passe em $1 um vetor 1536d gerado pelo mesmo modelo de embedding
SELECT id, conteudo,
1 - (embedding <=> $1::vector) AS similarity
FROM documentos
ORDER BY embedding <=> $1::vector
LIMIT 5;
Limitação: pgvector vai bem em muitos cenários com alguns milhões de vetores. Depois disso, RAM, SSD e padrão de consulta começam a mandar mais que a extensão em si. Se a carga subir demais, considere uma solução dedicada.
Métricas de distância: qual usar
Três opções principais. A escolha depende do modelo de embedding que gerou os vetores.
| Métrica | Fórmula (simplificada) | Quando usar | Modelos que usam |
|---|---|---|---|
| Cosine | Ângulo entre vetores | Default seguro, especialmente com embeddings normalizados | OpenAI, Azure OpenAI, Cohere |
| Euclidean (L2) | Distância geométrica | Quando o modelo ou benchmark foi calibrado pra L2 | Alguns pipelines com embeddings não normalizados |
| Dot Product | Multiplicação direta | Quando o modelo foi treinado pra inner product ou os vetores já estão normalizados | Recomendadores e embeddings pré-normalizados |
Na dúvida, use cosine. Nos embeddings da OpenAI e do Azure OpenAI, os vetores já saem normalizados, então cosine e dot product geram o mesmo ranking. Ainda assim, cosine costuma ser o default mais legível.
Operações do dia a dia
Backup e recovery
Vector databases precisam de backup como qualquer outro. Os vetores são dados derivados (gerados a partir de texto por um modelo de embedding), mas re-gerar 10 milhões de embeddings pode levar horas e custar centenas de dólares em API calls.
# Azure AI Search: não tem backup nativo "click-button"
# Estratégia: manter os dados fonte + pipeline de re-indexação
# Exportar uma página de documentos via Search API
az rest --method POST \
--url "https://meu-search.search.windows.net/indexes/meu-indice/docs/search?api-version=2026-04-01" \
--skip-authorization-header \
--headers Content-Type=application/json api-key=$SEARCH_QUERY_KEY \
--body '{
"search": "*",
"top": 1000,
"skip": 0,
"select": "id,content"
}'
Monitoring
Métricas que importam pra vector DB em produção:
- Query latency (p50, p95, p99): deve ficar < 50ms pra boa UX
- Index size vs available memory: se o índice não cabe em RAM, performance desaba
- Recall: % de resultados corretos (monitore via amostras)
- Indexing throughput: quantos vetores/segundo consegue ingerir
- Storage utilization: especialmente com quantização
# Azure AI Search: verificar estatísticas do índice
az rest --method GET \
--url "https://meu-search.search.windows.net/indexes/meu-indice/stats?api-version=2026-04-01" \
--skip-authorization-header \
--headers api-key=$SEARCH_ADMIN_KEY \
--query "{documentCount: documentCount, storageSize: storageSize}"
Scaling patterns
Vertical: mais RAM = mais vetores em HNSW. Mais CPU = buscas paralelas mais rápidas.
Horizontal (sharding): dividir vetores entre múltiplos nós. Cada nó busca no seu subset, results são merged. Azure AI Search faz isso automaticamente com partitions.
Tiered storage: vetores “quentes” (buscados frequentemente) em HNSW na RAM. Vetores “frios” em disco com IVF. Similar a hot/cool/archive tiers em storage.
O que levar pra segunda-feira
- Vector DB é um search engine especializado, não um banco relacional. Otimizado pra busca por similaridade, não pra queries complexas.
- HNSW domina mas come RAM. Quantização (int8) reduz 4x com perda mínima.
- Escolha de solução: se já tem PostgreSQL e está falando de alguns milhões de vetores, pgvector pode bastar. Se precisa de escala e features de busca, Azure AI Search é mais confortável. Se precisa de controle total, Qdrant self-hosted entra forte.
- Backup é importante mesmo sendo dado derivado. Re-gerar embeddings custa dinheiro e tempo.
- A métrica que importa é recall, não só latência. Busca rápida que devolve coisa irrelevante não ajuda ninguém.
Quando o time de ML te pedir um “vector database”, você já consegue devolver as perguntas certas: quantos vetores, qual recall aceitável, quanto cabe em RAM e como esse índice vai ser refeito. A partir daí, deixa de ser caixa preta e vira sistema operável.
Leitura complementar
- How Vector Databases Work (Neo Kim, System Design Newsletter)
- Azure AI Search vector search documentation
- pgvector documentation