Data

14 fev, 2017

Otimização de legibilidade e tempo de execução em consultas SQL no SGBD Oracle 11g

Publicidade

Uma boa estratégia de estar sempre à frente dos negócios é fornecer e buscar os dados da forma mais rápida possível para que eles auxiliem na tomada de decisões e ajudem a otimizar os processos da empresa.

Neste artigo, vou apresentar algumas técnicas de consulta para que essas informações cheguem até você no menor tempo possível com comandos super simples de SQL.

1. Use uma cláusula where para filtrar linhas

Uma boa dica para aqueles que estão iniciando com a linguagem SQL é adicionar uma cláusula where em uma consulta. Dessa forma, restringimos as linhas recuperadas apenas àquelas realmente necessárias.

Um exemplo disso são as consultas a seguir:

  • Digamos que você queira os detalhes de dois clientes, nº 1 e 3, da tabela customers. A consulta abaixo nos traz todos os resultados da tabela:
SELECT * FROM customers;

Resultado:

  • Adicionando uma cláusula where à consulta, obtemos apenas os clientes que desejamos.
SELECT * FROM customers 
WHERE customer_id IN (1,3);

Resultado:

Outra dica importante é evitar o uso de funções na cláusula where, uma vez que isso aumenta o tempo de execução.

2. Use referências de colunas totalmente qualificadas ao fazer JOINS

Sempre ponha apelidos nas tabelas de suas consultas e utilize o apelido de cada coluna (qualificar totalmente suas referências de coluna). Desse modo, o banco de dados não precisará procurar nas tabelas coluna utilizada em sua consulta.

O exemplo a seguir usa os apelidos p e pt para as tabelas products e product_types respectivamente, mas a consulta não qualifica totalmente as colunas description e price:

SELECT p.name, pt.name, description, price

FROM products p, products_types pt

WHERE p.product_type_id = pt.product_type_id.

Essa consulta funciona, mas o banco perde tempo em procurar as colunas description e price nas duas tabelas presentes na consulta. Isso porque não há um apelido que forneça as informações ao banco de dados em qual tabela essas colunas estão.

A consulta abaixo inclui o apelido de tabela p para qualificar totalmente as colunas description e price:

 

SELECT p.name, pt.name, p.description, p.price

FROM products p, products_types pt

WHERE p.product_type_id = pt.product_type_id.

Uma vez que todas as colunas estão com apelidos, o banco de dados não precisa perder tempo procurando por elas e, consequentemente, o tempo de execução é reduzido.

3. Substitua cálculos em várias consultas por expressões CASE

Todos sabemos que uma das coisas mais importantes na construção de relatórios é o retorno de informações numéricas para os usuários. Sendo assim, usar expressões CASE ao invés de várias consultas, resulta em ganho de performance e legibilidade do código.

O mau exemplo abaixo usa de várias consultas para contar o número de produtos dentro de diversos intervalos de preço:

  • SELECT COUNT(*) FROM products where price < 13;

  • SELECT COUNT(*) FROM products where price BETWEEN 13 AND 15;

  • SELECT COUNT(*) FROM products where price > 15;

Ao invés de usar três consultas, você deve escrever uma única que utilize expressões CASE. Segue isso no exemplo a seguir:

SELECT 
  COUNT(CASE WHEN price < 13 THEN 1 ELSE null END) low,
  COUNT(CASE WHEN price between 13 and 15 THEN 1 ELSE null END) med,
  COUNT(CASE WHEN price > 15 THEN 1 ELSE null END) high
FROM products;

Assim, nota-se que a palavra chave CASE ajuda bastante na hora de retornar consultas que envolvem cálculos para o usuário.

4. Use WHERE em vez de HAVING

A cláusula WHERE é usada para filtrar linhas; a cláusula HAVING, para filtrar grupos linhas. Como a cláusula HAVING filtra grupos de linhas depois que elas foram agrupadas, o que leva um tempo para ser feito, quando possível, devemos primeiro filtrar as linhas usando uma cláusula WHERE. Desse modo, você evita o tempo gasto para agrupar as linhas filtradas.

A consulta abaixo recupera o valor de product_type_id e o preço médio dos produtos cujo valor de product_type_id é 1 ou 2.

SELECT product_type_id, AVG(price)
FROM products
GROUP BY product_type_id
HAVING product_type_id IN (1, 2);

A consulta correta a seguir reescreve o exemplo anterior usando WHERE, em vez de HAVING, para primeiro filtrar as linhas naquelas cujo valor de product_type_id é 1 ou 2:

SELECT product_type_id, AVG(price)
FROM products
WHERE product_type_id in (1,2)
group by product_type_id;

Nota-se, claramente, o tempo poupado.

5. Use UNION ALL em vez de UNION

Usamos UNION ALL para retornar todas as linhas recuperadas por duas querys, incluindo as linhas duplicadas; UNION é utilizado para obter todas as linhas não duplicadas recuperadas pelas querys. Como UNION retira as linhas duplicadas, quando possível, devemos usar UNION ALL.

A consulta abaixo é inadequada para retornar as linhas das tabelas products e more_products. Veja que as linhas não duplicadas de products e more_products são recuperadas.

SELECT product_id, product_type_id, name FROM products
UNION
SELECT prd_id, prd_type_id, name FROM more_products;

A query a seguir reestrutura a consulta anterior para usar UNION ALL. Note que todas as linhas de products e more_products são recuperadas – incluindo as repetidas:

SELECT product_id, product_type_id, name FROM products
UNION ALL
SELECT prd_id, prd_type_id, name FROM more_products;

Existem outras dicas envolvendo outros processos do SQL para otimização de consultas, como utilizar paralelismo, explorar um excelente plano de indexação, dentre outros. Esse tipo de cuidado vai, com certeza, aumentar a velocidade com que sua empresa busca os relatórios, auxiliando assim, na tomada de decisões e elaboração de estratégias.