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 fazerJOIN 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 oJOIN 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 colunatotal_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.
GO TO FULL VERSION