CodeGym /Cursos /SQL SELF /Equilíbrio entre normalização e performance

Equilíbrio entre normalização e performance

SQL SELF
Nível 26 , Lição 3
Disponível

Quando a gente normaliza os dados direitinho, cada tabela fica super enxuta e a informação nela segue uma única ideia. Mas, pra rodar queries reais (tipo "Quais estudantes estão inscritos no curso de SQL?"), pode ser que você precise juntar um monte de tabelas. Quanto mais tabelas, mais complicado fica o query, mais o sistema "sua a camisa".

Provavelmente você já conhece os JOINs das aulas anteriores. Olha só um exemplo de query que pode aparecer quando você trabalha com um banco de dados bem projetado:

SELECT students.name, courses.title
FROM students
JOIN enrollments ON students.id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.id
WHERE courses.title = 'SQL';

Parece simples, mas por trás dos panos o servidor faz um trampo pesado: lê cada tabela, junta os dados, filtra... E se as tabelas forem gigantescas? Faz sentido imaginar que a performance vai cair.

Guerra: normalização vs velocidade

Por sorte (ou não?), na vida real banco de dados é sempre um compromisso. Normalização total garante integridade dos dados, mas deixa as queries complexas mais lentas. Se o banco vai ser usado pra analytics e relatórios, às vezes é melhor desnormalizar. É tipo trocar 10 caixinhas pequenas por um baúzão: pegar os dados fica mais rápido, mas organizar de novo dá mais trabalho.

Quando dá pra "relaxar" na normalização?

Existem cenários onde desnormalizar é melhor:

Agregados usados toda hora

Imagina que o sistema todo dia faz query pra contar quantos estudantes tem em cada curso. Na estrutura normalizada, você teria que fazer JOIN e COUNT() sempre. Em vez disso, dá pra colocar na tabela "Courses" uma coluna student_count, que é atualizada automaticamente quando alguém entra ou sai.

-- Coluna desnormalizada
UPDATE courses
SET student_count = (
    SELECT COUNT(*)
    FROM enrollments
    WHERE enrollments.course_id = courses.id
);

Relatórios feitos toda hora

Se o cliente pede todo dia um relatório tipo "Quem, onde, quando comprou?", é mais fácil guardar uma tabela desnormalizada com linhas prontas tipo "Nome do cliente, produto, data". A tabela vai ficar maior, mas a velocidade pra pegar os dados aumenta.

Muito mais leitura do que escrita

Quando o banco é usado basicamente pra leitura (tipo analytics), vale sacrificar a normalização pra ganhar velocidade.

Minimizar joins em relações complicadas

Se as tabelas têm relações multilayer (aninhadas), e o JOIN vira um pesadelo, corta alguns níveis de normalização.

Exemplo: como a desnormalização acelera?

Temos tabelas normalizadas de um e-commerce:

Tabela products Tabela orders Tabela order_items
id id id
name date order_id
price customer_id product_id
quantity

Cada pedido (orders) tem linhas de itens (order_items). Vamos calcular quanto dinheiro a loja faturou:

SELECT SUM(order_items.quantity * products.price) AS total_revenue
FROM order_items
JOIN products ON order_items.product_id = products.id;

O processo de juntar order_items e products deixa a query lenta quando tem muito dado.

Estrutura desnormalizada

Agora imagina que na tabela order_items tem uma coluna "extra" total_price (desnormalização):

Tabela order_items
id
order_id
product_id
quantity
total_price

Agora a query fica trivial:

SELECT SUM(total_price) AS total_revenue
FROM order_items;

Assim a gente evita o JOIN e ganha velocidade.

Exercício prático: otimizando o banco "Vendas"

Dado: tabelas normalizadas

Tabela products Tabela sales
id id
name product_id
price date
quantity

Desafio: acelerar queries do tipo "Quanto faturamos em cada produto?".

Passo 1: adiciona a coluna total_price na tabela sales:

ALTER TABLE sales ADD COLUMN total_price NUMERIC;

Passo 2: preenche essa coluna com os dados já existentes:

UPDATE sales
SET total_price = quantity * (
    SELECT price
    FROM products
    WHERE products.id = sales.product_id
);

Passo 3: faz as queries voarem:

SELECT product_id, SUM(total_price) AS total_revenue
FROM sales
GROUP BY product_id;

Mas! Desnormalizar tem seu preço

Você manja que "mais rápido" nem sempre é "melhor". Quando desnormaliza, aparecem uns problemas:

Armazenamento extra

A coluna total_price é uma cópia dos dados, ocupa mais espaço.

Atualizações mais complicadas

Se o preço do produto mudar na tabela products, você tem que atualizar a coluna total_price na mão. Isso pode dar inconsistência.

Anomalias em insert, update e delete

Os dados podem "desalinhar" fácil se esquecer de atualizar a parte desnormalizada. Tipo, mudou o preço do produto, mas não mudou automaticamente nos outros lugares.

Equilíbrio: como achar o ponto ideal?

Escolhe o que é mais importante: performance ou estrutura? Se o banco é muito lido, foca nas queries.

Desnormaliza só onde faz diferença. Tipo, só pros números chave e relatórios importantes.

Automatiza as atualizações dos dados desnormalizados. Usa triggers ou jobs pra evitar inconsistências.

2
Tarefa
SQL SELF, nível 26, lição 3
Bloqueado
Desnormalização para acelerar a contagem
Desnormalização para acelerar a contagem
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION