Pular para o conteúdo
Voltar para o acervo
Engenharia7 min de leituraPasso 21 de 22

Dados e analytics: do OLTP ao lakehouse

Duas perguntas aparecem em toda empresa: por que o relatório derrubou a produção, e por que o número do meu painel é diferente do seu. As duas têm a mesma causa raiz.

· Gabriel Dias
oltpolapcolunarcdc

Alguém rodou um relatório pesado no banco da aplicação e a latência do checkout dobrou. Alguém apresentou um número de receita e outra pessoa apresentou outro. As duas situações vêm do mesmo lugar: dado analítico e dado transacional foram tratados como se fossem a mesma coisa.

OLTP e OLAP: dois mundos

OLTP é o banco da aplicação. Muitas transações pequenas, cada uma tocando poucas linhas, escrita e leitura misturadas, latência de milissegundos. Armazenamento por linha, porque você quase sempre quer a linha inteira.

OLAP é o mundo da análise. Poucas consultas, cada uma varrendo milhões de linhas e agregando, e você tolera segundos. Armazenamento por coluna.

Por que colunar muda tudo: se você quer a soma de uma coluna sobre cem milhões de linhas, no formato por linha você lê tudo, inclusive as quarenta colunas que não interessam. No colunar, você lê só aquela coluna.

E como valores da mesma coluna são parecidos, comprimem muito melhor: dez vezes é comum. Menos byte lido é menos tempo e, na nuvem, literalmente menos dinheiro, porque a cobrança é frequentemente por byte processado.

É por isso que rodar relatório no banco da aplicação é ruim de duas formas: é lento, porque o formato é errado; e é perigoso, porque consome o mesmo recurso que atende o cliente pagante.

Os nomes que você vai encontrar: Parquet e ORC como formato de arquivo colunar; DuckDB para análise local, que é surpreendentemente eficiente; ClickHouse para análise em tempo real; BigQuery, Snowflake e Redshift como warehouse gerenciado.

OLTP: o banco da aplicação

  • Muitas transações pequenas, poucas linhas cada
  • Armazenamento por linha: você quer a linha inteira
  • Latência de milissegundos, escrita e leitura misturadas
  • Normalizado: cada fato mora num lugar só

OLAP: o mundo da análise

  • Poucas consultas varrendo milhões de linhas
  • Armazenamento por coluna: lê só a coluna que interessa
  • Comprime dez vezes melhor, e na nuvem isso é dinheiro
  • Desnormalizado de propósito: esquema estrela
Rodar relatório no banco da aplicação é lento pelo formato e perigoso pelo recurso.

Modelagem: normalizar ou desnormalizar

No OLTP você normaliza. Cada fato mora em um lugar só, e você evita anomalia de atualização. Terceira forma normal resolve quase tudo.

Duas armadilhas frequentes:

Exclusão lógica. Uma coluna deletado parece inofensiva e contamina todas as consultas para sempre. Alguém vai esquecer o filtro, e o bug vai ser sutil.

Guardar valor mutável apenas por referência. O preço do produto mudou, e o pedido de dois anos atrás agora mostra o valor errado. Pedido guarda o preço praticado, sempre. Isso não é desnormalização indevida: é registro histórico.

No OLAP você desnormaliza de propósito. O modelo é o esquema estrela: no centro, a tabela fato, com uma linha por evento, as medidas numéricas e as chaves. Em volta, as dimensões: cliente, produto, tempo, loja, cada uma larga e descritiva.

Funciona porque o analista escreve uma junção simples e o motor otimiza bem. Você troca normalização por velocidade e clareza, e num sistema onde ninguém atualiza linha, a duplicação não gera anomalia.

E o conceito que confunde: dimensão que muda lentamente, ou SCD. O cliente mudou de cidade.

Tipo 1: você sobrescreve e perde a história, e o relatório do ano passado passa a mostrar a cidade nova.

Tipo 2: você cria uma linha nova com data de início e fim, e mantém a história, e o relatório do ano passado continua correto.

Tipo 2 é mais trabalhoso e é o que você quer quando alguém pergunta "quanto vendemos em São Paulo em 2023".

Como o dado chega lá

ETL x ELT. ETL é a ordem clássica: extrai, transforma fora, carrega pronto. Fazia sentido quando o destino era caro e limitado.

ELT inverte: extrai, carrega cru, e transforma dentro do destino usando o poder dele. É o padrão hoje, e a vantagem prática é grande: se a regra de transformação estava errada, você reprocessa a partir do dado cru que já está lá, sem extrair de novo da origem.

Batch x streaming. Batch processa em janelas: de hora em hora, todo dia. Simples, barato, fácil de reprocessar. Streaming processa evento a evento, com latência de segundos, e é muito mais caro em complexidade: evento atrasado, janela de tempo, estado.

A pergunta certa antes de escolher streaming: alguém vai tomar uma decisão diferente por saber disso agora em vez de daqui a uma hora? Na maioria das vezes, não.

CDC (captura de mudança de dados) é como o dado sai do banco transacional hoje. Em vez de "select tudo" toda noite (que é pesado, perde deleções e perde estados intermediários), você lê o log de replicação do próprio banco. Você recebe cada insert, update e delete como um evento.

O cuidado com CDC no Postgres: o slot de replicação. Se o consumidor parar, o banco segura o WAL para ele, e o disco enche. Já derrubou muito banco de produção. Monitore o atraso do slot.

Warehouse, lake e lakehouse

Warehouse: estruturado e governado, com esquema definido na escrita. Ótimo para consumo, rígido para dado novo.

Lake: arquivo cru em armazenamento barato, com esquema na leitura. Flexível, e vira pântano se ninguém governar.

Lakehouse: a síntese. Arquivos abertos no armazenamento barato mais uma camada de metadados (Iceberg, Delta, Hudi) que traz transação, viagem no tempo e evolução de esquema.

Hoje, para começar do zero, é o padrão que eu escolheria.

E a organização em camadas: bronze é o cru, exatamente como chegou, imutável: é a sua rede de segurança para reprocessar. Prata é limpo, tipado, deduplicado. Ouro é agregado e pronto para o negócio.

Parece burocracia até o dia em que uma regra sai errada. Aí ela salva a semana, porque você reprocessa do bronze.

Confiança no dado

O jeito mais comum de um pipeline quebrar não é bug: é alguém no time da aplicação renomear uma coluna sem saber que dez painéis dependiam dela.

Contrato de dados é o acordo explícito entre quem produz e quem consome: esquema, significado de cada campo, garantias de frescor e volume, e o processo de mudança. Com contrato, quebrar vira violação detectável no pipeline do produtor, e não surpresa na sexta.

Teste de dado é diferente de teste de código: você testa o dado que passou, não a função:

Esquema: as colunas e tipos estão lá?

Volume: o número de linhas de hoje está na faixa esperada?

Distribuição: média e nulos parecidos com ontem?

Regra de negócio: nada negativo, nada no futuro, chaves batem.

Frescor é a métrica mais importante e a mais esquecida: quando essa tabela foi atualizada pela última vez? Dado velho servido como atual é pior que dado ausente, porque ausente todo mundo percebe.

Idempotência é a propriedade que separa pipeline profissional de artesanal: rodar duas vezes dá o mesmo resultado. A técnica padrão é sobrescrever por partição: em vez de inserir, você reescreve inteira a partição daquele dia. Reprocessar vira trivial, e você vai reprocessar muito mais vezes do que imagina.

Evento, partição e a métrica única

Se você é dev de aplicação, a sua maior contribuição ao time de dados é emitir evento bom: nome no passado (PedidoConfirmado, não ConfirmarPedido), identificador único para deduplicação, o instante em que aconteceu separado do de processamento, versão do esquema, e os dados que descrevem o fato, não referências que vão mudar depois.

E use o padrão outbox, para o evento e a gravação serem atômicos.

Particionamento no lado analítico: os arquivos ficam em pastas por data, e a consulta que filtra por data lê só aquelas pastas. Isso é poda de partição, e é a diferença entre varrer dois gigabytes e dois terabytes, o que na nuvem é a diferença entre centavos e centenas de reais na mesma consulta.

Cuidado com o extremo oposto: particionar por algo de alta cardinalidade gera milhões de arquivos minúsculos, e aí o custo vira abrir arquivo. O alvo é arquivo de algumas centenas de megabytes.

E o problema mais político: qual é a receita do mês? Marketing tem um número, financeiro tem outro. Nenhum está errado. Eles definiram diferente: com ou sem imposto, com ou sem cancelamento, na data do pedido ou do pagamento.

A solução é uma camada semântica: a métrica é definida uma vez, em código, versionada, e todo mundo consome dali. Ferramenta ajuda; o essencial é que alguém seja dono da definição.

Contra o hype

Para a maioria das empresas, a stack certa é: um warehouse gerenciado, dbt para transformação em SQL versionado, um orquestrador simples e um BI. Ponto.

Você não precisa de Kafka, Spark e data mesh para trinta gigabytes de dado. Trinta gigabytes cabem confortavelmente num DuckDB no seu laptop, e respondem em segundos.

Data mesh, especificamente, é um modelo organizacional: domínios sendo donos dos próprios dados como produto. Sem a mudança organizacional, adotar as ferramentas só distribui a bagunça.

Leia depois disto

Fala comigo

Dúvida sobre o artigo? Me chama no WhatsApp

Sem formulário e sem lista de e-mail. Se você discorda de alguma coisa que eu escrevi, ou quer contar como resolveu aí, a conversa é direta comigo.

Abrir conversa