Ao trabalhar com bancos de dados relacionais, frequentemente nos deparamos com a necessidade de contar registros relacionados em uma tabela. Uma forma de otimizar essas contagens é através da Denormalização de bancos de dados. Este artigo explora como a Denormalização de bancos de dados pode simplificar suas queries e aumentar significativamente a velocidade de suas operações.
Contando Registros Relacionados em Bancos de Dados
Para ilustrar, vamos considerar duas tabelas: orders (pedidos) e order_items (itens de pedido). A tabela orders contém informações sobre os pedidos, como o ID do pedido, a data do pedido e o cliente. A tabela order_items detalha os itens incluídos em cada pedido, com informações como ID do item, ID do pedido, produto e quantidade.
Em um cenário comum, podemos querer saber quantos itens cada pedido contém. Uma abordagem inicial seria utilizar uma subquery (subconsulta) com a função COUNT.
A consulta SQL para realizar essa contagem seria algo como:
SELECT
o.order_id,
(SELECT
COUNT(*) FROM order_items oi
WHERE oi.order_id = o.order_id
) AS total_items
FROM
orders o;
Embora essa consulta funcione, ela pode se tornar ineficiente com grandes volumes de dados, pois a subquery é executada para cada linha na tabela orders.
O que é Denormalização de bancos de dados?
**Denormalização de bancos de dados** é o processo de introduzir redundância em um banco de dados previamente normalizado. O objetivo é melhorar o desempenho das operações de leitura (queries). Isso envolve adicionar dados duplicados ou combinar tabelas para reduzir o número de operações necessárias, como joins e contagens. A Denormalização de bancos de dados acelera a recuperação de informações em sistemas onde as leituras são mais frequentes que as escritas.
Em vez de contar os itens cada vez que a query é executada, podemos adicionar um campo total_items diretamente na tabela orders. Sempre que um item for adicionado ou removido, incrementamos ou decrementamos esse campo.
Implementando a Denormalização de bancos de dados
Primeiro, adicionamos a coluna total_items à tabela orders:
ALTER TABLE orders ADD COLUMN total_items INT DEFAULT 0;
Em seguida, atualizamos o campo total_items sempre que itens são adicionados ou removidos. Com isso, a query se torna mais simples e eficiente:
SELECT
order_id,
total_items
FROM
orders;
Validando a Proposta com Dados de Exemplo
Para validar a proposta, podemos inserir dados de exemplo usando a seguinte função:
CREATE OR REPLACE FUNCTION generate_sample_data()
RETURNS VOID AS $$
DECLARE
order_count INT := 200;
items_per_order INT := 10;
current_order_id INT;
random_customer VARCHAR(100);
random_product VARCHAR(100);
random_quantity INT;
BEGIN
FOR i IN 1..order_count LOOP
random_customer := 'Customer ' || (floor(random() * 1000)::INT);
INSERT INTO orders (order_date, customer, total_items)
VALUES (current_date - (floor(random() * 365)::INT), random_customer, 10)
RETURNING order_id INTO current_order_id;
FOR j IN 1..items_per_order LOOP
random_product := 'Product ' || (floor(random() * 100)::INT);
random_quantity := (floor(random() * 10)::INT + 1);
INSERT INTO order_items (order_id, product, quantity)
VALUES (current_order_id, random_product, random_quantity);
END LOOP;
END LOOP;
END;
$$ LANGUAGE plpgsql;
SELECT generate_sample_data();
Este script cria 200 registros na tabela orders e 10 registros correspondentes na tabela order_items para cada pedido.
Para comparar o desempenho, executamos ambas as queries com EXPLAIN ANALYZE:
-
Usando Subquery:
Tempo de execução: 28.983ms
-
Usando Campo Desnormalizado:
Tempo de execução: 0.073ms (397x mais rápido). Note que este teste usou apenas 200 registros de pedido – os ganhos de desempenho se tornam mais significativos à medida que o volume de dados aumenta.
Se você precisa pausar seu plano pré-pago ou teme não conseguir pagar, veja suas opções.
Vantagens da Denormalização de bancos de dados
- Performance: Evita a execução repetitiva de subqueries.
- Simplicidade: Estrutura de query principal mais limpa.
- Controle: Gerenciamento direto dos valores do contador.
Considerações ao usar a Denormalização de bancos de dados
- Consistência: É crucial garantir que total_items sempre reflita contagens precisas.
- Concorrência: Requer atualizações atômicas em sistemas de alta concorrência.
Este conteúdo foi auxiliado por Inteligência Artificial, mas escrito e revisado por um humano.
Via Dev.to