🏗️ Arquitetura de Dados Moderna

Este documento é um manual técnico de referência para engenheiros de software, arquitetos e cientistas de dados — mas com uma escada didática para que um trainee consiga acompanhar. Cada família é analisada sob a ótica da engenharia real: arquitetura interna, trade-offs, anti-padrões documentados e integração com IA moderna. A versão 2.3 incorpora explicações conceituais com analogias simples, um glossário para iniciantes e contextualização de custo e carga operacional (FinOps).

Como usar

Navegue pela sidebar. As seções seguem o fluxo: tabular (Relacional → Colunar) → agregados (Documento, KV) → distribuídos (Wide-Column) → relacionamentos (Grafo) → especializados (TS, Search, Vetorial). Use Ctrl+K para busca. Termos densos como LSM Tree, MVCC, WAL, Sharding e Cardinalidade estão definidos no Glossário para Trainee.

Para o trainee

Se você está começando, leia primeiro o glossário e depois volte. Cada seção tem um bloco "Por baixo dos panos" com analogias do mundo real para os conceitos mais densos.

🗄️

9 Famílias

Relacional, Colunar, Documento, Key-Value, Wide-Column, Grafo, Time-Series, Search e Vetorial.

🔬

Profundidade Técnica

Storage engines, WAL, LSM Trees, MVCC, index-free adjacency, supernodes.

🤖

IA Moderna

RAG, embeddings, hybrid search (BM25 + vetor), memória de agentes.

⚠️

Anti-Padrões

Shard keys monotônicas, ES como fonte de verdade, modelagem relacional no Cassandra.

Como Escolher o Banco de Dados Correto

A escolha não deve ser guiada por hype. É uma decisão arquitetural que impacta latência, throughput, custo operacional, complexidade de código e resiliência a falhas.

Perguntas Fundamentais

  1. Qual o formato dos dados? Estruturado (tabelas), semiestruturado (JSON), grafos, séries temporais, vetores densos?
  2. Qual o padrão de acesso? Leitura pesada, escrita pesada, balanceado? Consultas pontuais ou analíticas?
  3. Qual a latência aceitável? Sub-ms (Redis), ms (PostgreSQL), segundos (BigQuery)?
  4. Qual o volume de dados? GB, TB, PB?
  5. Qual o modelo de consistência necessário? ACID estrito ou eventual aceitável?
  6. Qual a tolerância a falhas? Zero downtime? Recuperação em minutos?
  7. Qual o orçamento operacional? Self-hosted, managed cloud, serverless?

Matriz de Decisão

CenárioBanco RecomendadoAlternativaNotas
CRUD transacional + integridadePostgreSQLMySQL, CockroachDBACID mandatório
Catálogo / CMSMongoDBCouchbase, FirestoreSchema flexível
Cache de baixa latênciaRedisMemcachedSub-ms
Event sourcing / IoTCassandraScyllaDBWrite-heavy
Grafos sociais / RecomendaçãoNeo4jArangoDBTravessia profunda
Métricas / monitoringPrometheus + InfluxDBTimescaleDBTime-series nativo
Full-text searchElasticsearchOpenSearch, MeilisearchÍndice invertido
RAG / busca semânticaPinecone ou WeaviatePostgreSQL (pgvector)pgvector se já usa Postgres
Analytics / data warehouseClickHouseBigQuery, SnowflakeColunar, OLAP

Poliglot Persistence

Prática de usar diferentes tecnologias de armazenamento para diferentes necessidades dentro da mesma aplicação. Um e-commerce moderno pode usar:

  • PostgreSQL — pedidos, transações financeiras (ACID)
  • Redis — carrinho, sessões, rate limiting
  • Elasticsearch — busca de produtos (stemming, relevância)
  • Cassandra — eventos de navegação (write-heavy)
  • Pinecone — recomendações por similaridade semântica
graph LR
    A[API Gateway] --> B[Pedidos]
    A --> C[Busca]
    A --> D[Recomendação]
    B --> E[(PostgreSQL)]
    B --> F[(Redis)]
    C --> G[(Elasticsearch)]
    D --> H[(Pinecone)]
    B --> I[(Cassandra)]
                

1. Bancos Relacionais — Conceito & Modelo

Organizam dados em tabelas com schema rígido. Baseado na álgebra relacional de Codd (1970). Relações por chaves primárias e estrangeiras, garantindo integridade referencial.

Modelo Mental

Pense em um banco relacional como um conjunto matemático de fatos. Cada linha é uma proposição verdadeira. O SQL é declarativo: você descreve o que quer, o query planner decide como obter.

-- DDL + INSERT: como o dado é armazenado
        CREATE TABLE pedidos (
        id SERIAL PRIMARY KEY,
        cliente_id INTEGER NOT NULL REFERENCES clientes(id),
        valor_total NUMERIC(12,2) NOT NULL,
        status VARCHAR(20) DEFAULT 'pendente',
        criado_em TIMESTAMPTZ DEFAULT now()
        );
        INSERT INTO pedidos (cliente_id, valor_total, status)
        VALUES (42, 299.90, 'confirmado');

Características — ACID, CAP & Escalabilidade

ACID

  • Atomicidade: WAL garante tudo ou nada.
  • Consistência: Constraints e integridade referencial.
  • Isolamento: MVCC (PostgreSQL) ou locks (MySQL).
  • Durabilidade: WAL + fsync.

CAP Theorem — Contexto Correto

O teorema CAP aplica-se a sistemas distribuídos com replicação. Um PostgreSQL standalone não está sujeito a partições de rede — não há "P" para tolerar. Já bancos NewSQL como CockroachDB são nativamente CP (consistência + tolerância a partições).

Arquitetura Interna — B-Tree, MVCC & VACUUM

A maioria usa B-Trees como estrutura primária de índice. Cada nó ocupa uma página de disco (8KB no PostgreSQL). MVCC permite leituras não bloqueantes via snapshots. O VACUUM limpa versões obsoletas — falha em executá-lo causa bloat e degradação de performance.

Por baixo dos panos (analogias)

B-Tree é como o índice remissivo de uma enciclopédia: as páginas ficam ordenadas e o índice te leva rapidamente até a entrada certa em poucos saltos (O log N). Excelente para leitura por chave e busca por intervalo.

WAL (Write-Ahead Log) é como um caderno de rascunho de garçom: antes de mexer no caixa (disco principal), ele anota tudo na comanda. Se cair a luz, ao reabrir basta reler a comanda para reconstruir o estado. Garante durabilidade (D do ACID) sem precisar escrever no disco principal a cada operação.

MVCC (Multi-Version Concurrency Control) é como o Google Docs com histórico de versões: cada transação enxerga um snapshot consistente do banco e leituras nunca bloqueiam escritas. O preço é o "lixo" deixado por versões antigas, que o VACUUM precisa coletar periodicamente.

graph TD
    A[Cliente SQL] --> B[Parser]
    B --> C[Query Planner]
    C --> D[Executor]
    D --> E[Storage Engine]
    E --> F[B-Tree Index]
    E --> G[Heap / Table]
    E --> H[WAL Writer]
    H --> I[(Write-Ahead Log)]
                

SQL & Interfaces

-- Window function com cast explícito (evita divisão inteira)
        SELECT categoria, produto, receita,
        RANK() OVER (PARTITION BY categoria ORDER BY receita DESC) AS rank_cat,
        ROUND(receita::numeric / SUM(receita::numeric) OVER (PARTITION BY categoria) * 100, 2) AS pct
        FROM vendas_mensais WHERE data >= '2026-01-01'
        ORDER BY categoria, rank_cat;

Casos de Uso Reais (Validados)

  • Stripe: PostgreSQL para transações financeiras. ACID inegociável. Sharding com Citus.
  • Instagram: PostgreSQL com sharding lógico customizado (geração de IDs via PL/pgSQL, roteamento na aplicação). Não usam Vitess — Vitess é uma solução para MySQL criada pelo YouTube.
  • Uber: MySQL com Schemaless (camada interna de flexibilidade).
Nota de correção

Versões anteriores atribuíam Vitess ao Instagram/PostgreSQL. Isso estava incorreto. O Vitess foi criado pelo YouTube para escalar MySQL. O Instagram desenvolveu seu próprio sistema de sharding para PostgreSQL.

Quando NÃO Usar SQL

  • Full-text search: Elasticsearch oferece stemming e BM25 nativos.
  • Análise de petabytes: ClickHouse/BigQuery superam row-store.
  • Schema altamente variável: MongoDB ou Couchbase mais naturais.

Produtos Relevantes

BancoLicençaDestaqueLimitaçãoEmpresas
PostgreSQLMIT-likeExtensível, MVCC, JSONB, pgvectorReplicação multi-master complexaStripe, Instagram, Reddit
MySQLGPL/OracleAlta adoção, InnoDB robustoMenos extensível que PGUber, GitHub, YouTube
SQLitePublic DomainEmbedded, zero-config, single-writer (modo WAL permite leitores concorrentes ao escritor)Apenas um escritor por vez — contenção em apps com alta concorrência de escritaiOS, Android, Chrome
CockroachDBBSLNewSQL, CP nativo, PG wire-compatibleLatência > PG standaloneBose, Comcast
SQLite e o modo WAL

Por padrão, o SQLite usa o modo rollback journal, onde leitores bloqueiam escritores e vice-versa. Ativando o modo WAL (Write-Ahead Logging) com PRAGMA journal_mode=WAL, leituras passam a ocorrer em paralelo à escrita em andamento — só não pode haver dois escritores simultâneos. Essa nuance é vital para performance em apps móveis e desktop modernos, onde leitura concorrente é a regra.

IA & SQL

PostgreSQL + pgvector permite busca por similaridade de cosseno no SQL, mantendo metadados na mesma base — ideal para RAG sem dupla sincronização.

-- Busca semântica com pgvector
        SELECT documento_id, conteudo,
        1 - (embedding <=> query_embedding) AS similaridade
        FROM documentos ORDER BY embedding <=> query_embedding LIMIT 10;

2. Bancos Colunares / OLAP — Conceito & Row vs Column

Armazenam dados por coluna. Em um row-store (OLTP), todos os campos de uma linha ficam juntos na mesma página. Em um column-store (OLAP), cada coluna é armazenada separadamente, permitindo compressão extrema (10-20x) e scans eficientes para agregações.

Visualização: Como o disco enxerga seus dados

Considere uma tabela de vendas com 4 colunas (id, data, categoria, valor) e 3 linhas. Veja como cada arquitetura agrupa os bytes no disco:

graph TB
    subgraph ROW["🗄️ Row-Store (PostgreSQL, MySQL) — agrupado por LINHA"]
        R1["Bloco 1: [1 | 2026-05-12 | audio  | 299.90]"]
        R2["Bloco 2: [2 | 2026-05-12 | video  | 1499.00]"]
        R3["Bloco 3: [3 | 2026-05-13 | audio  | 89.50]"]
        R1 --> R2 --> R3
    end
    subgraph COL["📊 Column-Store (ClickHouse, BigQuery) — agrupado por COLUNA"]
        C1["Bloco id:        [1, 2, 3]"]
        C2["Bloco data:      [2026-05-12, 2026-05-12, 2026-05-13]"]
        C3["Bloco categoria: [audio, video, audio]"]
        C4["Bloco valor:     [299.90, 1499.00, 89.50]"]
        C1 --> C2 --> C3 --> C4
    end
                
Intuição prática

Para SELECT SUM(valor) FROM vendas:
Row-Store: precisa ler TODOS os blocos (id, data, categoria, valor) para extrair apenas a coluna valor. Desperdício de I/O.
Column-Store: lê apenas o bloco valor. Bônus: como valores semelhantes ficam juntos, a compressão chega a 10–20×.

Por isso row-stores ganham em OLTP (ler/atualizar uma linha inteira) e column-stores ganham em OLAP (agregar uma coluna sobre bilhões de linhas).

-- Query analítica no ClickHouse
        SELECT toStartOfDay(data) AS dia, categoria,
        SUM(receita) AS total, COUNT(DISTINCT usuario_id) AS usuarios
        FROM vendas WHERE data >= today() - 30
        GROUP BY dia, categoria ORDER BY dia DESC, total DESC LIMIT 100;
        -- Column-store lê apenas 4 colunas; row-store leria TODAS as colunas de cada linha.

⚠️ Colunar (OLAP) ≠ Wide-Column (NoSQL)

Distinção crítica

Colunar (ClickHouse, BigQuery): foco em compressão e agregações analíticas. Os dados são organizados por coluna para acelerar scans sequenciais e funções agregadas (SUM, AVG). Não foi feito para buscas pontuais por chave.

Wide-Column (Cassandra, ScyllaDB): foco em particionamento e escrita em massa. Os dados são organizados por row key + column families esparsas. Otimizado para gravações rápidas e disponibilidade, não para agregações analíticas.

Casos de Uso

  • Cloudflare: ClickHouse para análise de trilhões de eventos/dia.
  • Spotify: BigQuery para análise de streaming.
  • Capital One: Snowflake como data warehouse corporativo.

Produtos

BancoLicençaDestaqueLimitação
ClickHouseApache 2.0Rápido, compressão agressivaUpdates/Deletes custosos
BigQueryGCP ProprietárioServerless, escala a PBCusto por query, lock-in
SnowflakeProprietárioSeparação storage/computeCusto elevado
DuckDBMIT"SQLite para analytics"Não multi-user

3. Bancos de Documento — Conceito & Modelo

Armazenam documentos (JSON, BSON). Design orientado a agregados: dados relacionados são embedados, evitando JOINs. Schema flexível por documento.

// Documento MongoDB: dados relacionados embutidos
        db.produtos.insertOne({
        _id: ObjectId("684f1a2b3c4d5e6f7a8b9c0d"),
        nome: "Fone Bluetooth Pro",
        categoria: "áudio",
        preco: NumberDecimal("299.90"),
        variantes: [{ cor: "preto", estoque: 150 }, { cor: "branco", estoque: 80 }],
        avaliacoes: [{ usuario: "ana", nota: 4.5, comentario: "Ótimo som" }]
        });

Características — Tunable Consistency & Sharding

MongoDB moderno (4.0+) não é puramente BASE. Ele oferece consistência configurável (tunable consistency): transações ACID multi-documento, leituras com readConcern: "majority" e escritas com writeConcern: "majority". O modelo permite escolher entre performance e consistência por operação.

O custo real de subir a consistência

"Tunable" não é mágica: cada degrau acima na consistência custa latência. Veja a ordem de grandeza típica em um replica set de 3 nós:

NívelLatência típicaGarantiaQuando usar
w:1 (default antigo)~1msConfirmação só do primário. Perda de dados se ele cair antes de replicar.Logs, telemetria descartável
w:majority (default novo)~5–15msEspera maioria dos nós confirmarem. Sobrevive a falha de 1 nó.Dados de negócio padrão
w:majority + j:true~10–30msEspera fsync no journal de cada nó. Sobrevive a quedas de energia.Pagamentos, financeiro
readConcern: "linearizable"~20–100msLeitura mais recente garantida globalmente. Requer round-trip extra.Auditoria, regulado
Regra de bolso

Subir de eventual para majority custa de 3× a 10× mais latência. Vale para escritas críticas, é desperdício para logs e métricas. Configure por operação, não globalmente.

Sharding — Anti-Padrão Documentado

Hot shard por chave monotônica

Chaves de alta cardinalidade que crescem monotonamente (ObjectId, timestamp) direcionam todas as novas escritas para o mesmo shard. Use hashed sharding para distribuir escritas uniformemente quando a chave natural for monotônica. Range sharding é útil para queries por intervalo, mas perigoso com chaves sequenciais.

Arquitetura Interna

Storage engine WiredTiger: B-Trees + MVCC + compressão snappy. O oplog registra operações para replicação.

graph TD
    A[Driver] --> B[Mongos Router]
    B --> C[Config Servers]
    B --> D[Shard 1]
    B --> E[Shard 2]
    D --> F[(WiredTiger)]
    E --> G[(WiredTiger)]
                

Queries & APIs

// Aggregation pipeline
        db.vendas.aggregate([
        { $match: { data: { $gte: new Date('2026-04-01') } } },
        { $unwind: '$itens' },
        { $group: { _id: '$itens.categoria', total: { $sum: '$itens.preco' } } },
        { $sort: { total: -1 } }, { $limit: 10 }
        ]);

Casos de Uso Reais

  • Adobe: Creative Cloud — metadados de ativos com schema flexível.
  • eBay: Catálogo de produtos com milhões de SKUs.
  • Coinbase: Dados de exchange com histórico embutido.

Quando NÃO Usar

  • Relacionamentos N:N complexos: Use grafo ou relacional.
  • Relatórios analíticos pesados: Aggregation pipeline lento vs SQL colunar.

Produtos

BancoLicençaDestaqueLimitação
MongoDBSSPL/CloudAtlas, tunable consistencyRAM alto, licença controversa
CouchbaseApache 2.0SQL++ (N1QL), cache integradoComunidade menor
FirestoreGCP ProprietárioServerless, real-timeVendor lock-in

4. Bancos Key-Value — Conceito & Modelo

Modelo mais simples: chave → valor. Redis estende com listas, sets, sorted sets, hashes, streams. Latências em microssegundos.

// Redis: estruturas de dados
        SET usuario:42:session "abc123" EX 3600
        LPUSH fila:emails "bem-vindo:joao@exemplo.com"
        ZADD ranking:jogadores 1500 "alice" 1420 "bob"
        HSET produto:789 nome "Teclado" preco 199.90 estoque 45

Características

O event loop principal do Redis é single-threaded — a execução dos comandos acontece em uma única thread, o que garante atomicidade sem precisar de locks e dá previsibilidade de latência. Mas atenção: a partir do Redis 6.0, o I/O de rede (leitura/parsing de bytes do socket e escrita das respostas) pode ser delegado a múltiplas threads via io-threads. Em workloads com muitos clientes concorrentes, isso aumenta o throughput sem quebrar a atomicidade.

Meia-verdade comum

Dizer apenas que "Redis é single-threaded" é uma simplificação que pode levar a decisões ruins (ex: subdimensionar CPU em servidores com muitos clientes). O processamento de comandos é single-threaded; o I/O de rede não é mais. Tarefas de background como BGSAVE (RDB), BGREWRITEAOF e expiração lazy também rodam fora da thread principal.

Persistência: RDB (snapshots) + AOF (append-only file). Cluster com 16384 hash slots para sharding horizontal.

Arquitetura Interna

Estruturas otimizadas: SDS (strings O(1)), Skip Lists (sorted sets O(log N)), Quicklists, Rax (Radix Tree para streams).

graph LR
    A[Cliente] --> B[Event Loop]
    B --> C{Comando}
    C -->|SET| D[Hash Table]
    C -->|ZADD| E[Skip List]
    D --> F[(RAM)]
                

Casos de Uso

  • Twitter: Timeline cache.
  • GitHub: Job queues (Sidekiq), rate limiting.
  • OpenAI: Rate limiting e cache de API.

Produtos

BancoLicençaDestaqueLimitação
RedisRSALv2/SSPLEstruturas ricas, pub/sub, I/O multi-threaded (6.0+)RAM cara; execução de comandos ainda single-thread
DynamoDBAWS ProprietárioServerless, auto-scalingLock-in
MemcachedBSDMulti-threaded, simplesSem persistência

5. Bancos Wide-Column — Conceito & Modelo

Organizam dados em linhas com row key, mas cada linha pode ter colunas diferentes (modelo esparso). Colunas agrupadas em column families. Otimizado para escritas rápidas e escalabilidade horizontal. Não confundir com bancos colunares (OLAP) — veja a distinção na seção 2.

-- CQL (Cassandra): schema
        CREATE TABLE eventos_usuario (
        usuario_id UUID,
        timestamp TIMESTAMP,
        tipo TEXT,
        payload TEXT,
        PRIMARY KEY (usuario_id, timestamp)
        ) WITH CLUSTERING ORDER BY (timestamp DESC);

Modelagem Query-First — O Paradigma do Wide-Column

Diferentemente do modelo relacional (onde você modela entidades e normaliza), no Cassandra você modela para as queries que vai executar. Isso significa que você pode duplicar dados em múltiplas tabelas para atender a diferentes padrões de acesso. Não há JOINs — cada query deve bater em uma única tabela (ou partição).

-- Mesma informação modelada para DUAS queries diferentes
        -- Tabela 1: posts de um autor (query por autor)
        CREATE TABLE posts_por_autor (
        autor_id UUID,
        data TIMESTAMP,
        titulo TEXT,
        conteudo TEXT,
        PRIMARY KEY (autor_id, data)
        ) WITH CLUSTERING ORDER BY (data DESC);

        -- Tabela 2: posts por tag (query por tag)
        CREATE TABLE posts_por_tag (
        tag TEXT,
        data TIMESTAMP,
        autor_id UUID,
        titulo TEXT,
        PRIMARY KEY (tag, data)
        ) WITH CLUSTERING ORDER BY (data DESC);
        -- Os dados são duplicados. Isso é intencional e necessário no Cassandra.
        -- Tentar "normalizar" aqui seria um anti-padrão.
Regra de ouro

Modele suas tabelas a partir das queries, não das entidades. Se uma query nova surgir e não puder ser atendida pelas tabelas existentes, crie uma nova tabela com os dados duplicados. Isso é query-first modeling.

Arquitetura Interna — LSM Tree, Bloom Filters & Tombstones

Cassandra usa LSM Trees (Log-Structured Merge Trees). Escritas → MemTable (RAM) + Commit Log (WAL). Flush → SSTable imutável. Compaction mergeia SSTables, removendo tombstones (marcadores de deleção).

Por baixo dos panos — LSM Tree

B-Tree é como um índice de enciclopédia: bem organizado, ótimo para ler, mas cada atualização exige reorganizar páginas no lugar (escrita aleatória, lenta).

LSM Tree é como um diário de anotações: você sempre escreve no fim da página atual (RAM/MemTable) e, quando ela enche, arranca a folha e arquiva como SSTable imutável. Periodicamente, um "bibliotecário" (o processo de compaction) junta várias folhas antigas, descarta repetições e deleções (tombstones) e produz folhas novas, ordenadas.

Por que isso favorece a escrita? Toda escrita vira um append sequencial — o tipo de I/O mais barato em SSD e HDD. Em troca, leitura é mais cara (pode ter que olhar várias SSTables) e a compaction consome CPU e I/O em background. Por isso bancos LSM brilham em workloads write-heavy (IoT, logs, métricas, eventos).

Bloom Filter: estrutura probabilística em RAM que responde rapidamente se uma chave pode existir em uma SSTable (falso positivo possível, falso negativo não). É como um porteiro com lista de convidados aproximada: se ele diz "não está na lista", tem certeza; se diz "talvez esteja", você precisa confirmar entrando. Reduz I/O drasticamente em consultas pontuais.

graph TD
    A[Write] --> B[Commit Log]
    A --> C[MemTable]
    C -->|Flush| D[(SSTable)]
    E[Read] --> F[Bloom Filter]
    F --> C
    F --> D
                

Casos de Uso Reais

  • Netflix: Cassandra para bilhões de eventos de streaming/dia.
  • Apple: iCloud — 75.000+ nós gerenciando petabytes.
  • Discord: Migrou do Cassandra para ScyllaDB (2022) por problemas de GC da JVM em clusters massivos. Este case é a principal motivação para o ScyllaDB (C++, shard-per-core, latência consistente).

Produtos

BancoLicençaDestaqueLimitação
CassandraApache 2.0Escala linear, multi-DCGC pauses, sem JOINs
ScyllaDBAGPL/EnterpriseC++, 10x throughputCompatibilidade <100%
HBaseApache 2.0HDFS nativoComplexo, depende do Hadoop

6. Bancos de Grafo — Conceito & Modelo

Modelam dados como nós e arestas, ambos com propriedades. O poder está nas consultas de travessia (traversal) — encontrar caminhos, padrões e conexões indiretas.

// Cypher (Neo4j): estrutura e consulta
        CREATE (alice:User {name: 'Alice'})-[:FRIEND {desde: date('2024-01-15')}]->(bob:User {name: 'Bob'});

        -- Amigos de amigos (2º grau) que não são amigos diretos
        MATCH (eu:User {name: 'Alice'})-[:FRIEND]->(amigo)-[:FRIEND]->(amigo2)
        WHERE NOT (eu)-[:FRIEND]->(amigo2) AND eu <> amigo2
        RETURN amigo2.name, COUNT(*) AS conexoes LIMIT 10;

Index-Free Adjacency — O Diferencial dos Grafos

O conceito que diferencia bancos de grafo de relacionais é a index-free adjacency. Em um banco relacional, um JOIN entre usuarios e amizades requer busca em índice (O log N) para cada hop. Em um banco de grafo nativo, cada nó mantém ponteiros físicos diretos para seus vizinhos (arestas). Uma travessia de 3 hops no grafo é O(1) por hop — custo constante, independente do tamanho total do banco.

Por baixo dos panos — analogia

Imagine uma festa:
Relacional: para descobrir os amigos do João, você abre a lista de presença (índice), busca "João" (O log N), depois consulta a tabela de amizades. Para amigos dos amigos, repete tudo. A cada hop, o índice cresce com o número de pessoas.
Grafo nativo: o João tem um caderninho no bolso com nomes e endereços dos amigos. Você vai direto, sem consultar lista nenhuma. Cada hop é uma consulta direta (O(1)) — não importa se a festa tem 100 ou 100 milhões de pessoas.

Por isso travessias profundas (amigos-de-amigos-de-amigos, detecção de fraude por caminhos suspeitos, recomendação por similaridade de comunidade) são ordens de grandeza mais rápidas em bancos de grafo nativos.

Mini-aside sobre complexidade: O log N significa "tempo cresce proporcional ao logaritmo do tamanho dos dados" — buscar em 1 bilhão de registros custa ~30 saltos em uma B-Tree. O(1) significa "tempo constante" — não muda com o tamanho. Para 1 hop a diferença é pequena; para 5 hops em grafo gigante, é a diferença entre milissegundos e minutos.

Supernodes — O Calcanhar de Aquiles

Um supernode é um nó com um número extremamente alto de arestas (ex: uma celebridade com milhões de seguidores). Travessias que passam por supernodes degradam performance drasticamente, pois todas as arestas precisam ser avaliadas. Em produção, é comum modelar supernodes com meta-arestas ou limitar a profundidade da travessia.

Casos de Uso

  • LinkedIn: Grafo de conexões profissionais — "pessoas que você talvez conheça".
  • PayPal: Detecção de fraude via padrões em grafos de transações.
  • NASA: Neo4j para dependências entre componentes de engenharia.

Produtos

BancoLicençaDestaqueLimitação Técnica
Neo4jGPLv3/EnterpriseCypher, index-free adjacencySharding de grafos é complexo (supernodes)
ArangoDBApache 2.0Multi-modelo (grafo+doc+KV)Performance de travessia inferior a bancos nativos de grafo
Amazon NeptuneAWS ProprietárioManaged, Gremlin/SPARQLVendor lock-in, custo elevado

7. Bancos Time-Series — Conceito & Modelo

Otimizados para dados com timestamp. Operações típicas: inserções sequenciais, consultas por intervalo e agregações temporais.

Retention Policies & Continuous Downsampling

Diferentemente de um colunar comum, TSDBs possuem retention policies (ex: deletar dados brutos após 30 dias) e continuous downsampling — agregação automática de dados antigos em resoluções menores (1s → médias de 1min → médias de 1h).

-- Exemplo InfluxDB (Flux simplificado)
        from(bucket: "metricas")
        |> range(start: -30d)
        |> filter(fn: (r) => r._measurement == "cpu")
        |> aggregateWindow(every: 1h, fn: mean)
        |> yield(name: "cpu_horaria")

Casos de Uso

  • Netflix: Atlas (InfluxDB) para 200M+ métricas.
  • Uber: M3 para observabilidade de microserviços.
  • CERN: InfluxDB para sensores do LHC.

Quando NÃO Usar TSDB

Anti-padrões de TSDB
  • Atualizações frequentes em registros passados: TSDBs assumem dados imutáveis e append-only. Updates retroativos são caros e, em alguns engines, simplesmente não suportados de forma performática.
  • Volumes moderados de dados temporais: Se você tem < 100GB e poucos milhares de inserções por segundo, PostgreSQL com índice em created_at + BRIN ou TimescaleDB resolve com menos complexidade operacional.
  • Queries relacionais complexas (JOINs): InfluxDB não tem JOIN tradicional. Se sua análise exige cruzar séries com dimensões de negócio complexas, considere ClickHouse ou um data warehouse.
  • Alta cardinalidade de tags: InfluxDB (TSM) degrada severamente quando o produto cartesiano de tags ultrapassa milhões de séries únicas. Use Prometheus + Thanos ou ClickHouse nesses casos.

Produtos

BancoLicençaDestaqueLimitação
InfluxDBMIT/CloudFlux, TSM engineAlta cardinalidade de tags
TimescaleDBApache 2.0/TSExtensão PG, hypertablesCompressão < InfluxDB
PrometheusApache 2.0Pull model, CNCFLongo prazo via Thanos/Cortex

8. Bancos de Search — Conceito & Modelo

Elasticsearch: construído sobre Apache Lucene, usa índices invertidos. Relevância via BM25. Índices em shards.

// Elasticsearch: mapeamento e indexação
        PUT /produtos
        { "mappings": { "properties": {
        "nome": { "type": "text", "analyzer": "portuguese" },
        "preco": { "type": "float" },
        "categoria": { "type": "keyword" }
        }}}
        POST /produtos/_doc
        { "nome": "Fone Bluetooth", "preco": 299.90, "categoria": "áudio" }

Casos de Uso

  • Uber: Busca de endereços e geocoding.
  • Tinder: Matching geo-espacial.
  • Wikipedia: Full-text em milhões de artigos.

Produtos

BancoLicençaDestaqueLimitação
ElasticsearchELv2/SSPLELK, Kibana, MLRAM, tuning complexo
OpenSearchApache 2.0Fork AWS compatívelComunidade consolidando
MeilisearchMITLeve, typo-tolerantMenos features

9. Bancos Vetoriais — Conceito & Embeddings

Armazenam e indexam vetores densos (embeddings) de 300 a 4096 dimensões. Algoritmo dominante: HNSW — grafo em múltiplas camadas, busca O(log N) aproximada.

# Embedding + upsert no Pinecone
        from openai import OpenAI
        from pinecone import Pinecone
        emb = OpenAI().embeddings.create(
        model="text-embedding-3-large",
        input="Fone Bluetooth com cancelamento de ruído"
        ).data[0].embedding
        Pinecone().Index("produtos").upsert(
        vectors=[("prod-789", emb, {"nome": "Fone Bluetooth Pro"})]
        )

RAG & IA Generativa

Retrieval-Augmented Generation: chunking → embedding → armazenamento → busca dos K chunks mais similares → injeção no prompt do LLM.

graph LR
    A[Documentos] --> B[Chunking]
    B --> C[Embedding]
    C --> D[(Banco Vetorial)]
    E[Pergunta] --> F[Embedding]
    F --> D
    D --> G[Top-K Chunks]
    G --> H[Prompt]
    H --> I[LLM]
    I --> J[Resposta]
                

Hybrid Search — O Estado da Arte em 2026

Ninguém usa apenas busca vetorial pura em produção. O padrão moderno é hybrid search: combinar resultados de busca vetorial (similaridade semântica) com busca lexical (BM25 / texto pleno) e fundi-los via Reciprocal Rank Fusion (RRF) ou pesos ajustados (weighted scoring).

graph TD
    A[Query do Usuário] --> B[Embedding da Query]
    A --> C[Análise Lexical]
    B --> D[Índice HNSW]
    C --> E[Índice Invertido BM25]
    D --> F[Top-K Vetorial]
    E --> G[Top-K Lexical]
    F --> H[Fusão RRF]
    G --> H
    H --> I[Resultado Final Ranqueado]
                

Bancos como Weaviate e Elasticsearch (8.x+) oferecem hybrid search nativo. O Pinecone recentemente adicionou suporte a sparse vectors para permitir a mesma fusão. Essa combinação captura tanto a intenção semântica quanto a precisão de palavras-chave exatas.

Quando NÃO Usar Banco Vetorial

Anti-padrões de vetorial
  • Volume pequeno (< 1M vetores): Um índice pgvector HNSW em PostgreSQL resolve sem custo extra de SaaS dedicado. Pinecone só compensa em escala.
  • Busca exata por palavra-chave: Para "encontrar produto cujo SKU é ABC-123", índice invertido (Elasticsearch) ou simples B-Tree são ordens de grandeza mais rápidos e baratos. Vetorial é para significado, não literal.
  • Filtros complexos como critério primário: Se 90% das queries filtram por país + categoria + preço e só 10% precisam de similaridade, o vetorial vira gargalo. Use SQL com filtros + reranking por similaridade no final.
  • Dados que mudam toda hora: Re-embedding em massa é caro (latência + custo do modelo). Vetorial brilha em corpora relativamente estáveis (docs, catálogo, base de conhecimento).
  • Substituir banco transacional: Vetorial não tem ACID, não é fonte de verdade. Mantenha PG/Mongo como master e o vetorial como índice secundário (igual ao papel do Elasticsearch).

Produtos

BancoLicençaÍndiceHybrid SearchLimitação
PineconeSaaSHNSW+PQSparse vectors (beta)Lock-in, custo
WeaviateBSD-3HNSWNativo (BM25+vetor)Self-hosted requer tuning
QdrantApache 2.0HNSWFiltros + vetorEcossistema novo
pgvectorMITIVFFlat/HNSWVia SQL + tsvectorMenos otimizado
Pinecone vs pgvector

São alternativas, não complementares. Use Pinecone/Weaviate se precisar de hybrid search avançado. Use pgvector se já estiver no ecossistema PostgreSQL e quiser evitar sincronização de dois bancos.

Tabela Comparativa Geral

Agora com duas colunas extras para apoiar decisões de mundo real: 💰 Custo Relativo (TCO típico em escala média — $ barato, $$$$ caro) e 🛠️ Carga Operacional (esforço de setup + manutenção em produção).

FamíliaModeloConsistênciaEscalaLatência💰 Custo🛠️ Op. BurdenPrincipal
RelacionalTabelasACIDVertical (+ shard)1-10ms$$Baixo (managed) / Médio (self)PostgreSQL
Colunar/OLAPColunasEventualHorizontal massiva100ms-10s$$$ (BigQuery) / $ (DuckDB)MédioClickHouse
DocumentoJSONTunableHorizontal1-10ms$$$ (Atlas)Médio (replica set + shard)MongoDB
Key-ValueKVEventual/ForteHorizontal<1ms$$$$ (RAM!)Baixo (Redis), Zero (DynamoDB)Redis
Wide-ColumnRows+ColsEventualHorizontal linear1-5ms$$Alto (clusters, GC, compaction)Cassandra
GrafoNós+ArestasACIDVertical (+ shard)5-50ms$$$ (Enterprise)Médio-Alto (sharding complexo)Neo4j
Time-SeriesTimestampEventualHorizontal1-10ms$$Médio (retention, downsampling)InfluxDB
SearchÍndice InvertidoEventualHorizontal10-100ms$$$ (RAM + disco)Alto (tuning de mapping/analyzer)Elasticsearch
VetorialVetoresEventualHorizontal5-50ms$$$$ (SaaS) / $$ (self)Baixo (SaaS), Médio (self)Pinecone
Sobre-engenharia mata startups

Escolher Cassandra ou Neo4j para um MVP com 2 devs e 3 semanas de prazo é o tipo de decisão que afunda o produto antes dele validar mercado. Comece com PostgreSQL + Redis em quase todos os casos — eles cobrem ~80% dos cenários até centenas de milhares de usuários, com carga operacional baixa. Migre para soluções especializadas só quando a dor for real e mensurável.

Glossário Para o Trainee

Os termos mais densos do material, explicados sem usar mais jargão. Use como referência rápida ao ler outras seções.

TermoO que é (em uma frase)AnalogiaOnde aparece
ACIDGarantias de transação: Atomicidade, Consistência, Isolamento, Durabilidade.Caixa eletrônico que ou completa a transferência inteira, ou não tira nada da sua conta.Relacional, MongoDB 4+
BASEBasically Available, Soft state, Eventual consistency — alternativa relaxada ao ACID.Curtida no Instagram: pode aparecer agora ou em 200ms; o sistema converge.NoSQL, Cassandra
CAPEm uma partição de rede, você escolhe entre Consistência ou Disponibilidade.Telefone cortado: ou você confia na última info que ouviu (A), ou desliga e pede para repetir (C).Sistemas distribuídos
PACELCExtensão do CAP: mesmo SEM partição, troca latência (L) por consistência (C).Drive-thru: confirmar pedido com gerente (consistência) vs. já entregar (latência).Modelos distribuídos modernos
WALWrite-Ahead Log: registrar a operação em um log antes de aplicar nos dados.Comanda do garçom: anota antes de mexer no caixa.PostgreSQL, Cassandra, SQLite
MVCCMulti-Version Concurrency Control: cada transação vê seu snapshot, leituras não bloqueiam escritas.Google Docs com histórico — cada um vê sua revisão consistente.PostgreSQL, MongoDB, Oracle
B-TreeÁrvore balanceada de busca, ótima para leitura ordenada e por chave.Índice remissivo de enciclopédia.Quase todo banco relacional
LSM TreeLog-Structured Merge — escreve sempre no fim (rápido), depois mergeia em background.Diário de anotações: você sempre escreve na última página.Cassandra, RocksDB, ScyllaDB
SSTableSorted String Table: arquivo imutável e ordenado gerado pelo flush da MemTable.Página arquivada do diário — não muda mais, fica catalogada.LSM-based DBs
TombstoneMarcador de deleção em LSM — o registro continua até a compaction limpá-lo.Post-it "EXCLUÍDO" colado em cima de uma anotação no diário.Cassandra, ScyllaDB
CompactionProcesso de mesclar SSTables, removendo duplicatas e tombstones.Bibliotecário juntando folhas antigas e refazendo a organização.LSM-based DBs
Bloom FilterEstrutura em RAM que diz "talvez exista" ou "definitivamente não existe".Porteiro com lista aproximada de convidados.Cassandra, HBase
ShardingDividir os dados em pedaços (shards) hospedados em máquinas diferentes.Lista telefônica dividida por inicial da letra entre 26 prédios.Sistemas distribuídos
Hashed ShardingAplicar hash na chave para distribuir uniformemente.Fila do banco: senha aleatória sorteada, não por ordem de chegada.MongoDB, DynamoDB
CardinalidadeQuantos valores distintos uma coluna/tag tem.Coluna "país" tem cardinalidade baixa (~200); coluna "user_id" tem altíssima.Índices, TSDBs
Index-Free AdjacencyCada nó já guarda ponteiro físico para os vizinhos — sem precisar de índice.Caderninho de telefone no bolso vs. consultar a lista telefônica toda vez.Neo4j, grafos nativos
SupernodeNó com altíssimo grau (milhões de arestas) — gargalo em travessias.Cristiano Ronaldo no Instagram: ninguém quer iterar pelos 600M seguidores.Grafos sociais
O(log N)Tempo cresce muito devagar com o tamanho — 1 bilhão = ~30 saltos.Subir escada onde cada degrau dobra a área coberta.B-Tree, HNSW
O(1)Tempo constante — não importa o tamanho dos dados.Pegar a chave do bolso, sempre o mesmo gesto.Hash table, grafo nativo (por hop)
HNSWHierarchical Navigable Small World: grafo em camadas para busca vetorial aproximada.Atlas com mapas em zoom — começa no mundo, desce até o bairro.Pinecone, Weaviate, pgvector
EmbeddingVetor numérico que representa o "significado" de um texto/imagem.Coordenadas no mapa cultural — "rei" e "rainha" ficam pertinho.RAG, busca semântica
BM25Algoritmo clássico de relevância em busca por palavra-chave.Score do Google antiga escola: importa frequência + raridade do termo.Elasticsearch, Lucene
RRFReciprocal Rank Fusion: combinar rankings de fontes diferentes em um único.Soma dos lugares no pódio — quem ficou bem em várias provas, vence.Hybrid search
OLTPOnline Transaction Processing — muitas operações pequenas (CRUD).Caixa do supermercado: muitas transações curtas.PostgreSQL, MySQL
OLAPOnline Analytical Processing — poucas queries enormes (agregações).Relatório de fim de mês: lê milhões, escreve um número.ClickHouse, BigQuery
Quorum / MajorityConfirmação por mais da metade dos nós da réplica.Votação no condomínio — só passa com maioria.Cassandra, MongoDB

Teorema PACELC — Indo Além do CAP

O CAP Theorem só fala sobre o que acontece durante uma partição de rede. Mas, na prática, a maior parte do tempo o sistema não está particionado — e mesmo assim precisa decidir entre latência e consistência. É aí que entra o PACELC, proposto por Daniel Abadi (2010):

A regra completa

Partition? Então escolha entre Availability e Consistency (clássico CAP).
Else (sem partição), escolha entre Latency e Consistency.

SistemaDurante partiçãoSem partiçãoClassificação PACELC
PostgreSQL (single)N/A (não distribuído)Prefere consistência
MongoDB (default)Mantém consistência (CP)Prefere consistênciaPC/EC
CassandraMantém disponibilidade (AP)Prefere latênciaPA/EL
DynamoDB (eventual)APPrefere latênciaPA/EL
DynamoDB (strong)CPPrefere consistênciaPC/EC
CockroachDBCPPrefere consistênciaPC/EC
Por que importa na prática

Quando você lê documentação de banco distribuído, atenção ao "E": é ali que se decide se sua leitura vai retornar em 2ms (eventual, replicada local) ou em 20ms (lendo quorum global). Partição é raro; latência é todo dia. O PACELC obriga o arquiteto a pensar nos dois cenários.

Erros Comuns na Escolha de Banco

Erro #1 — Modelar Cassandra como Relacional

Tentar normalizar dados no Cassandra (criar tabelas como se fosse PostgreSQL) é o erro mais comum. Cassandra exige query-first modeling: duplique dados, crie uma tabela para cada query. JOINs não existem.

Erro #2 — Elasticsearch como fonte de verdade

ES é índice secundário. Risco de perda de dados em split-brain é real. Mantenha a fonte primária em outro banco.

Erro #3 — Shard key monotônica

ObjectId/timestamp como shard key sem hashed sharding = hot shard. Sempre avalie se a chave é monotônica.

Tendências 2026

  • Hybrid Search como padrão: BM25 + vetor via RRF. Weaviate, ES e Pinecone competem nesse espaço.
  • Serverless databases: Neon (PG), Planetscale (MySQL), DynamoDB.
  • DuckDB: "SQLite para analytics" — análise local em Parquet/CSV/JSON.
  • NewSQL em ascensão: CockroachDB, YugabyteDB — PostgreSQL wire-compatible com consistência distribuída nativa (CP).
  • FinOps em bancos vetoriais: Custo de transferência de dados em SaaS (Pinecone) vs self-hosted (pgvector/Qdrant) é fator de decisão crescente.