System Design/02 - Componentes/Databases2 min
Denormalization
- Que problema isso resolve?
- Quando usar / quando NÃO usar?
- Qual o principal trade-off?
- Como isso falha em produção?
Conceito
Introduzir redundância deliberada — duplicar dados ou pré-computar agregados — para eliminar junções e acelerar leitura.
normalizado: pedidos ⋈ clientes ⋈ enderecos (3 tabelas, 2 junções)
desnormalizado: pedidos (com nome_cliente, cidade) (1 tabela, 0 junções)
Formas comuns
| Técnica | Exemplo |
|---|---|
| Coluna duplicada | nome_cliente dentro de pedidos |
| Contador pré-calculado | total_comentarios no post |
| Agregado materializado | Total de vendas por dia (Materialized View) |
| Documento embutido | Itens dentro do documento do pedido |
| Tabela de leitura dedicada | CQRS |
Trade-offs
O ganho é direto: leitura sem junção, frequentemente uma ordem de grandeza mais rápida — e, num sistema particionado, a diferença entre possível e impossível, já que junções entre shards não existem.
O custo é manter a cópia coerente. Quando o cliente muda de nome, todas as cópias precisam ser atualizadas. Isso pode ser feito por trigger, por evento assíncrono ou por job de reconciliação, e cada opção tem seu modo de falha:
| Mecanismo | Risco |
|---|---|
| Trigger no banco | Lentidão na escrita; lógica escondida |
| Evento assíncrono | Janela de inconsistência; evento perdido |
| Job periódico | Divergência até a próxima execução |
O trade-off honesto é escrita mais cara e mais arriscada em troca de leitura mais barata. Só compensa quando a razão leitura:escrita é alta — e é por isso que a decisão exige medir antes.
Vale também distinguir duplicação de snapshot intencional: guardar o preço do produto dentro do pedido não é desnormalização, é registrar um fato histórico. O preço mudou depois; o pedido deve preservar o que foi cobrado. Confundir os dois leva a "corrigir" dados que estavam certos.
E o alerta prático: desnormalizar cedo demais é otimização prematura que trava a evolução do schema. Normalize primeiro, meça, e desnormalize onde a medição apontar.
Exemplo prático
Uma listagem de posts que precisa exibir o número de comentários. Com COUNT(*) numa tabela de milhões de comentários, cada linha da listagem custa uma varredura.
A desnormalização é uma coluna total_comentarios no post, incrementada a cada comentário. A listagem passa a ler um inteiro.
O que se assume em troca: se um comentário for inserido e o incremento falhar, o contador fica errado — e ninguém percebe até alguém conferir. Por isso contadores desnormalizados costumam vir acompanhados de um job de reconciliação periódico, que recalcula e corrige a deriva.
Relacionado
Parte de Databases · roadmap.sh/system-design