Hoje, pra fechar essa jornada épica pelo PL/pgSQL, bora deixar claro: errar em procedimentos analíticos é inevitável. Por quê? Porque em analytics a gente lida com dados gigantes, cálculos cabulosos e, às vezes, umas condições bem malucas. Quanto mais complexo o query ou procedimento, mais ele parece um labirinto — um passo errado e já era, resultado errado na certa.
Por sorte, a maioria dos erros é manjada e dá pra prever (e evitar). Bora ver um por um.
1. Falta de índices nos campos chave
Índices são tipo um GPS no mundo dos bancos de dados. Sem eles, o banco tem que sair andando linha por linha na tabela. Em tabelas pequenas, até vai, mas quando os dados chegam a milhões de linhas, suas queries ficam mais lentas que Windows XP num Pentium III.
Imagina que você tem uma tabela de pedidos e quer calcular as vendas do último mês:
SELECT SUM(order_total)
FROM orders
WHERE order_date >= CURRENT_DATE - INTERVAL '1 month';
Se o campo order_date não tiver índice, o PostgreSQL faz um scan completo na tabela (Seq Scan). E isso quase sempre é devagar.
Como resolver? Usa índices! Só rodar esse comando:
CREATE INDEX idx_order_date ON orders (order_date);
Agora o PostgreSQL vai buscar na tabela pelo campo order_date bem mais rápido.
Uso de queries ineficientes
Tem query que até parece bonita, mas funciona igual um tijolo de concreto no lugar da chave. Tipo usar subqueries que poderiam ser trocadas por um JOIN, ou filtrar demais sem necessidade.
Tipo assim:
SELECT product_id, SUM(order_total)
FROM orders
WHERE product_id IN (SELECT id FROM products WHERE category = 'electronics')
GROUP BY product_id;
Melhor fazer assim:
SELECT o.product_id, SUM(o.order_total)
FROM orders o
JOIN products p ON o.product_id = p.id
WHERE p.category = 'electronics'
GROUP BY o.product_id;
Assim o PostgreSQL não precisa rodar subquery pra cada linha e tudo fica bem mais rápido.
Estrutura errada de tabelas temporárias
Tabelas temporárias podem ser uma mão na roda, se você usar direito. Mas se esquecer de colocar as colunas certas ou índices, a tabela temporária vira um gargalo e trava tudo.
Exemplo: vamos criar uma tabela temporária pra cálculos intermediários:
CREATE TEMP TABLE temp_sales AS
SELECT region, SUM(order_total) AS total_sales
FROM orders
GROUP BY region;
Mas aí você precisa filtrar pela coluna total_sales, e não tem índice nesse campo.
Antes de usar tabela temporária, pensa em como vai trabalhar com ela. Se precisar filtrar por uma coluna, já cria o índice:
CREATE INDEX idx_temp_sales_total_sales ON temp_sales (total_sales);
Erros nos cálculos (tipo divisão por zero)
Divisão por zero é clássico em analytics. SQL não vai fingir que não viu — ele simplesmente vai quebrar sua query.
Imagina que você quer calcular o valor médio dos pedidos:
SELECT SUM(order_total) / COUNT(*) AS avg_order_value
FROM orders;
Se a tabela orders estiver vazia, vai rolar divisão por zero e erro na certa.
Pra evitar, trata o caso em que o contador é zero:
SELECT
CASE
WHEN COUNT(*) = 0 THEN 0
ELSE SUM(order_total) / COUNT(*)
END AS avg_order_value
FROM orders;
Falta de logging e controle de execução
Procedimentos em PL/pgSQL podem ser complexos e ter várias etapas: de cálculos intermediários até relatórios finais. Se der ruim em algum ponto e não tiver logging, você nunca vai saber onde e por quê tudo deu errado.
Imagina que você cria um procedimento pra calcular métricas, mas esquece de checar os dados esperados em cada etapa. Aí tudo quebra quando aparece dado inesperado (tipo tabela vazia).
Pra evitar isso, coloca logging em cada etapa importante do procedimento. Exemplo:
RAISE NOTICE 'Início do cálculo de vendas';
-- Seu código aqui...
RAISE NOTICE 'Módulo % finalizado com sucesso', modulo;
Se o procedimento for mais complexo, melhor ainda salvar os logs numa tabela especial:
CREATE TABLE log_analytics (
log_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
log_message TEXT
);
No procedimento, adiciona:
INSERT INTO log_analytics (log_message)
VALUES ('Procedimento finalizado com sucesso');
Problemas de performance por falta de otimização
Otimizar não é só pra query, mas também pros procedimentos. Se muita gente usa o mesmo procedimento, ele pode virar gargalo no sistema.
Exemplo: um procedimento que recalcula métricas pra todas as regiões, mesmo quando só precisa de uma:
CREATE OR REPLACE FUNCTION calculate_sales()
RETURNS VOID AS $$
BEGIN
-- Recalcula pra todas as regiões
INSERT INTO sales_metrics(region, total_sales)
SELECT region, SUM(order_total)
FROM orders
GROUP BY region;
END;
$$ LANGUAGE plpgsql;
Isso gera processamento desnecessário.
Como resolver? Permita filtrar os dados, passando a região como parâmetro:
CREATE OR REPLACE FUNCTION calculate_sales(p_region TEXT)
RETURNS VOID AS $$
BEGIN
INSERT INTO sales_metrics(region, total_sales)
SELECT region, SUM(order_total)
FROM orders
WHERE region = p_region
GROUP BY region;
END;
$$ LANGUAGE plpgsql;
Assim o procedimento não processa dado à toa e a query termina mais rápido.
Ignorar ferramentas de análise de performance
Ferramentas tipo EXPLAIN ANALYZE são seus brothers — mostram onde a query tá travando e como melhorar. Se você escreve procedimento e não analisa a performance, é tipo programador de computador quântico sem osciloscópio — parece que funciona, mas ninguém sabe o que tá rolando de verdade.
Exemplo: o problema nesse query aparece fácil com EXPLAIN ANALYZE:
SELECT *
FROM orders
WHERE EXTRACT(YEAR FROM order_date) = 2023;
Essa query é ruim porque a função EXTRACT() impede o uso de índices.
Pra resolver, analisa a query assim:
EXPLAIN ANALYZE
SELECT *
FROM orders
WHERE order_date >= DATE '2023-01-01' AND order_date < DATE '2024-01-01';
Como evitar os erros mais comuns?
Pra não cair nessas armadilhas, segue essas dicas:
- Use índices nos campos que você filtra ou faz JOIN.
- Otimize as queries: corte subqueries desnecessárias, use
JOIN. - Faça logging da execução. Isso facilita muito o debug se der ruim.
- Sempre teste seus procedimentos com ferramentas tipo
EXPLAIN ANALYZE. - Viu problema de performance? Pense em particionar tabelas ou repensar a lógica da query.
Agora você tá pronto pra prever e evitar erros que poderiam deixar seus analistas sem café e sem Wi-Fi por causa de queries lentas.
GO TO FULL VERSION