System Design — Armazenamento (Lake + OLAP + Warehouse)
Data Lake (S3) para raw, OLAP (ClickHouse) para hot path, Warehouse (BigQuery) para cold path.
Definição
Camada de armazenamento separa dois caminhos por SLA. (1) Data Lake (S3) — evento cru, imutável, barato, em Parquet particionado por data. Fonte da verdade. (2) OLAP (ClickHouse/Druid) — banco colunar otimizado para agregação rápida. Hot path: query de dashboard em segundos sobre bilhões de linhas. (3) Data Warehouse (BigQuery/Redshift) — dados modelados (star schema) para BI e ML. Cold path: atualizado em batch, otimizado para análises complexas.
Problema → Solução
Problema
Guardar tudo num único banco SQL não escala (bilhões de linhas, latência alta). Sem raw imutável, mudança de regra de negócio significa perder histórico. Sem OLAP, dashboard demora minutos. Sem warehouse, BI/ML pesado mata o sistema operacional.Solução
Lambda/Kappa architecture: Lake é a fonte da verdade (raw), OLAP é o cache quente (agregado), Warehouse é a análise pesada (modelado). Se uma regra muda, replay do Lake recria os outros dois. ClickHouse com materialized views pré-agrega; warehouse alimenta-se de batch noturno do Lake.Dica de entrevista
Tip
Particionamento é tudo: no Lake, particione por data (year=2026/month=05/day=20). No ClickHouse, ORDER BY (event_date, event_name) — alinha I/O sequencial. Materialized views no ClickHouse para agregações comuns (eventos por hora, por SKU) — query roda em ms.Código
-- ClickHouse: tabela de eventos para hot path
CREATE TABLE events_olap (
event_date Date,
event_name LowCardinality(String),
event_id UUID,
session_id String,
user_id String,
sku String,
price Decimal(10,2),
device LowCardinality(String),
-- ...
timestamp DateTime64
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(event_date)
ORDER BY (event_date, event_name, session_id)
TTL event_date + INTERVAL 90 DAY;
-- Materialized view pré-agregada (atualiza ao inserir)
CREATE MATERIALIZED VIEW events_hourly
ENGINE = SummingMergeTree
PARTITION BY toYYYYMM(event_date)
ORDER BY (event_date, hour, event_name)
AS SELECT
event_date,
toHour(timestamp) AS hour,
event_name,
count() AS events,
uniq(session_id) AS sessions
FROM events_olap
GROUP BY event_date, hour, event_name;
-- Query do dashboard (roda em ms)
SELECT hour, events, sessions
FROM events_hourly
WHERE event_date = today()
AND event_name = 'add_to_cart'
ORDER BY hour;Perguntas de entrevista
Q.Por que ClickHouse e não Postgres para OLAP?▾
A.ClickHouse é colunar: armazena cada coluna separadamente, otimizado para agregação (count, sum, avg) sobre bilhões de linhas. Postgres é row-based: ótimo para OLTP (uma linha por vez) mas lento para analytics. ClickHouse comprime ~10x mais e roda agregações 100-1000x mais rápido em datasets grandes.
Q.O que é Lambda Architecture?▾
A.Dois caminhos paralelos: speed layer (stream processing, segundos de latência, aproximado) e batch layer (reprocessamento periódico, exato). Query layer combina os dois. Resolve o trade-off entre latência e correção. Kappa simplifica: só stream processing, com replay para recalcular.
Q.Por que evento cru imutável no Lake?▾
A.Replay: se você descobrir um bug no processor depois de 6 meses, pode reprocessar todos os eventos crus do Lake e regerar OLAP/Warehouse com a regra corrigida. Sem o raw, esses 6 meses de dados estão corrompidos para sempre. Imutável + barato (Parquet em S3) = garantia futura.
108/122← →