🚀 Novembro começou! O SQLtest.online continua gratuito graças às doações de pessoas como você. Ajude-nos a atingir a meta deste mês mais cedo para que o site continue funcionando sem interrupções. Apoiar agora →
Código SQL copiado para a área de transferência

Consultas SQL eficientes: como escrever SQL mais rápido e leve

Lição 10.2 · Tempo de leitura: ~10 min · Tarefas para praticar ↓

Esta lição apresenta fundamentos para escrever consultas SQL de alto desempenho. Você vai aprender como evitar carga desnecessária no banco, por que SELECT * costuma prejudicar performance e como filtrar dados de forma eficiente. Também veremos técnicas práticas para acelerar consultas em grandes volumes. Ao final, você conseguirá escrever SQL eficiente e responsável com recursos do servidor.

Na lição anterior, focamos em legibilidade para pessoas. Mas o SQL também precisa ser eficiente para o mecanismo do banco. Até uma consulta bem formatada pode ser lenta se obrigar o servidor a executar trabalho desnecessário.

A eficiência de consulta afeta diretamente a velocidade de aplicações e relatórios. Em cenários de alto volume, a diferença entre "funciona" e "otimizado" pode ser enorme.

SGBDs modernos possuem otimizadores potentes, mas eles não conhecem toda a lógica de negócio e não corrigem tudo automaticamente. Qualidade de SQL continua sendo responsabilidade do desenvolvedor.

Diagrama com técnicas para acelerar consultas SQL: filtragem, índices, otimização de JOIN e limite de resultados


Regra de ouro: busque apenas o necessário

Uma causa comum de lentidão é transferir dados demais entre servidor e cliente.

Evite SELECT *

SELECT * é útil em exploração inicial, mas deve ser evitado no SQL final.

  • Tráfego extra: você retorna colunas que não precisa.
  • Menos chance de plano com índice cobrindo colunas: pedir tudo dificulta planos mais eficientes.
  • Código frágil: novas colunas podem alterar performance e comportamento.
-- Ruim
SELECT * FROM film;

-- Melhor
SELECT film_id, title, release_year
FROM film;

Otimização de filtragem

A forma de limitar linhas determina quanto trabalho o SGBD vai fazer.

Filtre no servidor o quanto antes

Aplique WHERE antes de operações pesadas. Quanto menos linhas seguirem para JOIN e GROUP BY, melhor.

Evite funções em WHERE (consultas SARGable)

Para aproveitar índices, predicados devem ser SARGable. Se você envolve uma coluna indexada em função, o otimizador pode deixar de usar o índice de forma eficiente.

-- Lento (Non-SARGable)
SELECT count(*) 
FROM rental 
WHERE YEAR(rental_date) = 2005;

-- Rápido (SARGable)
SELECT count(*) 
FROM rental 
WHERE rental_date >= '2005-01-01' AND rental_date < '2006-01-01';

Trabalhando com JOIN

Junções estão entre as operações mais custosas em SQL.

  • Filtre antes de juntar sempre que possível.
  • Verifique índices nas chaves de relação.
  • Evite CROSS JOIN sem necessidade real.
  • Use EXISTS para testes de existência.
-- Menos eficiente
SELECT DISTINCT c.first_name, c.last_name
FROM customer c
JOIN payment p ON c.customer_id = p.customer_id;

-- Mais eficiente para existência
SELECT c.first_name, c.last_name
FROM customer c
WHERE EXISTS (
    SELECT 1 FROM payment p WHERE p.customer_id = c.customer_id
);

Use LIMIT durante validação

Ao depurar, use LIMIT para evitar retorno acidental de milhões de linhas.

SELECT customer_id, first_name, last_name
FROM customer
WHERE active = 1
LIMIT 10;

Exemplo prático: otimizando um relatório

Suponha que precisamos encontrar filmes alugados mais de 30 vezes em uma categoria específica.

Abordagem menos eficiente:

SELECT f.title, COUNT(r.rental_id)
FROM film f
JOIN inventory i ON f.film_id = i.film_id
JOIN rental r ON i.inventory_id = r.inventory_id
JOIN film_category fc ON f.film_id = fc.film_id
JOIN category c ON fc.category_id = c.category_id
WHERE c.name = 'Action'
GROUP BY f.title
HAVING COUNT(r.rental_id) > 30;

Abordagem mais eficiente: Se soubermos o ID da categoria, podemos evitar um JOIN adicional.

SELECT f.title, COUNT(r.rental_id) AS rental_count
FROM film f
JOIN film_category fc ON f.film_id = fc.film_id
JOIN inventory i ON f.film_id = i.film_id
JOIN rental r ON i.inventory_id = r.inventory_id
WHERE fc.category_id = 1 -- Usa ID em vez de busca textual
GROUP BY f.film_id, f.title
HAVING COUNT(r.rental_id) > 30;

Observação: filtrar por ID numérico costuma ser mais rápido do que filtrar por nome textual e pode reduzir joins desnecessários.


Principais conclusões desta lição:

  • Evite SELECT * em consultas de produção.
  • Filtre cedo com WHERE.
  • Escreva condições SARGable para permitir uso de índices.
  • Use EXISTS para verificação de existência.
  • Use LIMIT na exploração e depuração.
  • Prefira filtros por chaves numéricas.

Perguntas frequentes

Por que SELECT * é ruim em produção?

Ele retorna colunas desnecessárias, aumenta tráfego e pode piorar planos de execução. Listar colunas explicitamente é mais seguro.

O que significa SARGable na prática?

Significa permitir busca eficiente por índice. Funções em colunas indexadas costumam atrapalhar isso.

Quando usar EXISTS em vez de JOIN?

Quando você só precisa saber se existe linha relacionada e não precisa retornar colunas da tabela secundária.

Perguntas de entrevista

Quais primeiros passos você toma ao encontrar consulta SQL lenta?

Verifico SELECT *, seletividade de WHERE e predicados não SARGable. Depois avalio a estratégia de join e volume de linhas processadas.

Por que filtrar cedo melhora desempenho?

Porque reduz linhas envolvidas em joins, ordenações e agregações, diminuindo o custo total do plano.

Diferença de performance entre JOIN e EXISTS?

JOIN combina conjuntos de linhas e é necessário quando você precisa de colunas de ambas as tabelas. EXISTS costuma ser melhor para verificações sim/não.

Tente resolver as tarefas a seguir para reforcar o que voce aprendeu nesta licao.

  1. Quais filtros podem usar o índice em rental_date?
  2. Clientes com pagamentos, cada um uma só vez