Normalização resolve vários problemas, mas em alguns casos acaba criando outros, principalmente quando o assunto é performance. Hoje a gente vai abrir pra você os portões dessa arte meio sombria (às vezes iluminada) — a desnormalização. Sim, você pode quebrar as regras da normalização... mas tem que ser com inteligência!
Desnormalização é o processo oposto da normalização. Se a normalização separa as tabelas em entidades lógicas pra minimizar redundância, a desnormalização junta os dados de novo pra melhorar a performance. Ela é muito usada quando, sob carga pesada e consultas complexas rolando toda hora, o monte de JOIN começa a deixar o sistema lento.
Dá pra dizer que desnormalização é um equilíbrio entre a pureza dos dados e a velocidade das consultas.
Quando usar desnormalização?
Como qualquer ferramenta, é importante saber quando a desnormalização faz sentido. Ela entra em cena nessas situações:
Consultas muito usadas ficam lentas. Quando o sistema tá sob carga pesada e faz sempre as mesmas consultas (tipo relatórios e agregações), os JOINs de várias tabelas podem demorar demais. Desnormalizar ajuda a reduzir a quantidade desses JOINs.
Tarefas analíticas e estatísticas. Em sistemas de analytics (tipo BI — Business Intelligence), geralmente rola análise pesada de dados. Nesses casos, desnormalizar acelera o processamento porque os dados já estão "pré-preparados".
Consultas complexas. Se pra rodar uma query você precisa juntar cinco, dez ou até mais tabelas, isso pode deixar o banco bem devagar. Desnormalizar simplifica a estrutura das consultas.
Quando o número de JOINs passa do limite do bom senso. Se você tem query com 25 tabelas no
JOIN, talvez seja hora de repensar o seu modelo.
Exemplos de desnormalização
Exemplo 1: Loja online. Num banco normalizado de uma loja online, a gente teria tabelas assim:
customers— dados dos clientes.orders— informações dos pedidos.products— dados dos produtos.order_items— produtos que fazem parte do pedido.
A consulta pra pegar as informações pode ser mais ou menos assim:
SELECT
c.customer_name,
o.order_date,
p.product_name,
oi.quantity
FROM
customers c
JOIN
orders o ON c.customer_id = o.customer_id
JOIN
order_items oi ON o.order_id = oi.order_id
JOIN
products p ON oi.product_id = p.product_id
WHERE
c.customer_id = 42;
Mas e se a nossa loja online processa centenas de milhares de pedidos por dia? Essa query vai ficar lenta demais por causa do monte de JOIN.
Solução: desnormalização.
Bora criar uma tabela pra guardar as infos mais usadas:
CREATE TABLE order_summary AS
SELECT
c.customer_id,
c.customer_name,
o.order_id,
o.order_date,
p.product_id,
p.product_name,
oi.quantity
FROM
customers c
JOIN
orders o ON c.customer_id = o.customer_id
JOIN
order_items oi ON o.order_id = oi.order_id
JOIN
products p ON oi.product_id = p.product_id;
Agora, quando a gente quiser pegar os dados, é só consultar a order_summary:
SELECT * FROM order_summary WHERE customer_id = 42;
Exemplo 2: Sistema de analytics. Imagina que você trabalha num banco de dados de uma empresa que vende ingressos pra eventos. Tem as tabelas:
events— informações dos eventos.sales— dados das vendas dos ingressos.
Se o pessoal de analytics precisa montar um relatório da média de receita por ingresso em todos os eventos, a estrutura normalizada faz você rodar uma query agregada toda vez:
SELECT
e.event_name,
AVG(s.price) AS avg_ticket_price
FROM
events e
JOIN
sales s ON e.event_id = s.event_id
GROUP BY
e.event_name;
Essa query pode ser bem lenta, principalmente se cada venda ocupa milhões de linhas.
Solução: desnormalização. Vamos criar uma tabela separada com os dados agregados:
CREATE TABLE event_summary AS
SELECT
e.event_id,
e.event_name,
COUNT(s.sale_id) AS ticket_count,
SUM(s.price) AS total_revenue,
AVG(s.price) AS avg_ticket_price
FROM
events e
JOIN
sales s ON e.event_id = s.event_id
GROUP BY
e.event_id, e.event_name;
Agora os relatórios vão rodar mais rápido no nível agregado:
SELECT
event_name,
avg_ticket_price
FROM
event_summary;
Consequências da desnormalização
Desnormalizar pode sim deixar as consultas mais rápidas, mas não é uma varinha mágica que resolve tudo. Olha só o que pode rolar se você for por esse caminho.
Primeiro — duplicação de dados. Quando a mesma info fica em vários lugares, o tamanho do banco cresce rapidão e fica mais difícil de lidar.
Segundo — atualizar os dados fica mais complicado. Imagina que você tem os dados do cliente na tabela customers e também uma cópia na order_summary. Se o cliente trocar o nome ou endereço, tem que lembrar de atualizar nos dois lugares. Se esquecer, já era: os dados ficam diferentes e dá ruim.
Terceiro — com tanta redundância, é fácil se perder e cometer erro. Tipo ter várias versões do mesmo documento — às vezes nem dá pra saber qual é a certa.
E por fim, manter e evoluir esse banco fica mais difícil. Vai ter que criar trigger ou script pra garantir que todas as cópias dos dados fiquem sincronizadas. É trampo extra pra galera de dev.
Resumindo, desnormalização é uma ferramenta que tem que ser usada com consciência, sabendo os prós e contras.
GO TO FULL VERSION