Índices IVFFlat vs HNSW
pgvector oferece IVFFlat (inverted file com quantização grosseira) e HNSW (hierarchical navigable small world) para busca aproximada do vizinho mais próximo. Escolha com base nas metas de recall, orçamento de RAM e tolerância ao tempo de build.
Receita
-- IVFFlat: agrupa listas, sonda no momento da consulta
CREATE INDEX ON documents
USING ivfflat (embedding extensions.vector_cosine_ops)
WITH (lists = 100);
SET ivfflat.probes = 10;
-- HNSW: índice de grafo (pgvector 0.5+, escolha padrão para muitas cargas de trabalho)
CREATE INDEX ON documents
USING hnsw (embedding extensions.vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
SET hnsw.ef_search = 40;Quando usar isso: Tabela excede ~50k vetores e ORDER BY distance LIMIT k exato falha em atingir o SLO de latência.
Exemplo de Trabalho
-- Benchmark de recall vs latência (executar em staging com conjunto de consultas rotulado)
EXPLAIN (ANALYZE, BUFFERS)
SELECT id, embedding <=> $1 AS dist
FROM documents
ORDER BY embedding <=> $1
LIMIT 10;
-- Comparar varreduras de índice
DROP INDEX IF EXISTS documents_ivfflat_idx;
CREATE INDEX documents_ivfflat_idx ON documents
USING ivfflat (embedding extensions.vector_cosine_ops) WITH (lists = 200);
DROP INDEX IF EXISTS documents_hnsw_idx;
CREATE INDEX documents_hnsw_idx ON documents
USING hnsw (embedding extensions.vector_cosine_ops)
WITH (m = 16, ef_construction = 128);
-- Medir: latência p50/p95, recall@10 vs força bruta em consultas de amostraO que isso demonstra:
- IVFFlat precisa de ajuste de
listseivfflat.probesno momento da consulta - HNSW expõe
m,ef_constructionno build ehnsw.ef_searchna consulta EXPLAIN ANALYZEconfirma varredura de índice vs varredura sequencial- A medição de recall requer um padrão ouro de força bruta em consultas retidas
Mergulho Profundo
IVFFlat
Build: Clusters k-means (lists centróides). Cada vetor atribuído à lista mais próxima.
Consulta: Pesquisa as probes listas mais próximas, depois a distância exata dentro dessas listas.
| Parâmetro | Efeito |
|---|---|
lists | Mais listas = células menores, índice maior, build mais lento |
ivfflat.probes | Maior = melhor recall, consultas mais lentas |
Prós: Menor uso de memória que HNSW para algumas formas de dados; maduro em versões mais antigas do pgvector.
Contras: Recall sensível à distribuição dos dados; necessita de REINDEX após grandes mudanças nos dados; listas devem escalar com a regra de ouro sqrt(rows).
-- Heurística de lists para N linhas: sqrt(N) a N/1000
-- 1M de linhas: lists entre 1000 e 10000 dependendo dos benchmarksHNSW
Build: Grafo em camadas conectando vizinhos.
| Parâmetro | Efeito |
|---|---|
m | Máximo de arestas por nó (16 comum) |
ef_construction | Lista de candidatos no tempo de build (maior = melhor grafo, build mais lento) |
hnsw.ef_search | Lista de candidatos no tempo de consulta (maior = melhor recall, mais lento) |
Prós: Forte recall/latência padrão para pgvector 0.8+; menos sensível à ordem de inserção que IVFFlat.
Contras: Maior uso de RAM durante o build; índice maior em disco; interações de vacuum precisam ser monitoradas em escala.
Matriz de Decisão
| Fator | Preferir IVFFlat | Preferir HNSW |
|---|---|---|
| Prioridade de Recall | Moderada, ajustável com probes | Alta de fábrica |
| RAM de Build | Orçamento mais apertado | Pode liberar RAM |
| Inserções constantes | Reconstruir IVFFlat em lote periodicamente | HNSW lida melhor com inserções |
| Versão do pgvector | Restrições legadas | Padrão de produção 0.8+ |
| SLO de latência de consulta | Flexível | p95 estrito |
Manutenção de Índice
-- Após importação em lote de embeddings
REINDEX INDEX CONCURRENTLY documents_hnsw_idx;
ANALYZE documents;
-- Monitorar índices inválidos
SELECT indexrelid::regclass FROM pg_index WHERE NOT indisvalid;Armadilhas
- IVFFlat antes dos dados serem carregados - Build de tabela vazia gera centróides inúteis. Correção: Construir o índice após a carga em lote ou usar
REINDEXapós a conclusão da importação. - lists = 1 - Recall absurdo. Correção: Começar com
sqrt(n)e testar probes em um script de benchmark. - ef_search muito baixo - HNSW perde vizinhos. Correção: Aumentar
hnsw.ef_searchaté que o recall@k se estabilize em um conjunto de referência. - Incompatibilidade de Opclass - Ainda o principal problema do pgvector. Correção:
vector_cosine_opscom<=>. - Falha no build CONCURRENTLY - HNSW inválido deixado para trás. Correção: Remover o índice inválido; reduzir picos de
maintenance_work_memou construir fora do horário de pico sem CONCURRENTLY em um clone vazio. - Comparando maçãs com laranjas - k diferente, métricas diferentes. Correção: k fixo=10, mesmas 100 consultas, mesmo operador de distância para todas as execuções.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Varredura Exata | < 10k linhas | Corpus de milhões de linhas |
| HNSW Particionado por tenant | Multi-tenant massivo | Tenants pequenos, sobrecarga de operações |
| Serviço ANN Externo | PG falha comprovadamente em escala | Pipelines de recuperação com muitas junções |
| IVFFlat agora, HNSW depois | Emergência de memória | Você pode arcar com uma reconstrução |
FAQs
Recomendação padrão PG 18?
HNSW com m=16, ef_construction=64-128; ajuste ef_search por alvo de recall.Posso ter ambos os índices?
Apenas um deve ser usado pelo planejador; remova o não utilizado para economizar espaço.HNSW Halfvec?
Suportado em versões recentes do pgvector; reduz o armazenamento pela metade quando o modelo permite.Build de índice paralelo?
Use max_parallel_maintenance_workers; o build HNSW consome muita CPU e RAM.Atualizações "quentes"?
Atualizações frequentes de embeddings fragmentam o grafo; agende REINDEX se o recall se desviar.ANN Filtrado?
Índices parciais por tenant ou predicado de metadados; pgvector carece de pré-filtragem rica em todas as versões.Limites na nuvem?
Algumas instâncias gerenciadas limitam maintenance_work_mem; afeta o sucesso do build.Probes IVFFlat por sessão?
SET ivfflat.probes no pool de conexões ou SET LOCAL na transação.Script de benchmark?
Exporte 100 embeddings de consulta; compare os top-10 ids com força bruta.Atualizar de 0.7 para 0.8?
Leia as notas de lançamento; planeje REINDEX após ALTER EXTENSION UPDATE.Relacionado
- Noções Básicas do pgvector - operadores e tipos
- pgvector em Escala - memória e vacuum
- Esquema de Armazenamento RAG - layout do esquema
- REINDEX CONCURRENTLY - reconstrução online
- Melhores Práticas do pgvector - não confie nos padrões
Versões da Stack: Esta página foi escrita para PostgreSQL 18.4 (stable 18, maintenance 17), pgvector 0.8+, PostGIS 3.5+, pgbouncer 1.x, e Patroni 3.x.