CodeGym /Cursos /SQL SELF /Exemplos de desnormalização de dados e suas consequências...

Exemplos de desnormalização de dados e suas consequências

SQL SELF
Nível 25 , Lição 4
Disponível

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:

  1. 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.

  2. 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".

  3. 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.

  4. 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:

  1. customers — dados dos clientes.
  2. orders — informações dos pedidos.
  3. products — dados dos produtos.
  4. 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:

  1. events — informações dos eventos.
  2. 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.

1
Pesquisa/teste
Normalização de dados, nível 25, lição 4
Indisponível
Normalização de dados
Normalização de dados
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION