Performance: A velocidade está nos detalhes

Já apresentei alguns pontos sobre como trabalhar com grande volumes de dados em Oracle em um post anterior (clique aqui para visualizá-lo), agora minha intenção é te mostrar que desenvolver uma funcionalidade com bom desempenho só é possível se você se atentar aos detalhes.
No post anterior eu foquei em ferramentas avançadas (merge, bulk collect, forall). Neste post eu vou comentar sobre comandos muito simples, mas que podem ser uma ameaça à performance se forem usados de forma inadequada.

Já ouviu a expressão “Se está funcionando, não mexa!”
Já ouvi estudantes de faculdade utilizando esta expressão quando entregam seus trabalhos: “O código não está tão bonito, mas está funcionando, então está ótimo.”

Em casos como este, provavelmente se passarmos a funcionalidade por um teste de carga, encontraremos problemas.

Lembre-se: a diferença está nos detalhes!
Vou te mostrar abaixo alguns exemplos de comandos que geram o mesmo resultado, mas que podem deixar o software mais lento ou mais rápido dependendo de como são utilizados.

 

1. Count x Exists

Não são todos os casos em que é possível trocar um COUNT por EXISTS, mas quando for possível será mais rápido, porque o COUNT precisa percorrer a tabela toda para contar cada linha que atenda às condições, já o EXISTS retorna TRUE ao encontrar o primeiro registro que atenda às condições.

Toda vez que eu preciso contar para validar se a quantidade é zero, é possível trocar o COUNT pelo EXISTS como nos exemplos a seguir. A Listagem 1 apresenta o código com COUNT. A Listagem 2 apresenta o mesmo funcionamento utilizando EXISTS.

select count(1)
into   vnQuantNotasComFreteFOB
from   nota_fiscal
where  trunc(data) = to_date('01/04/2015') and
       tipo_frete = 'FOB';

if vnQuantNotasComFreteFOB = 0 then
  [faça alguma coisa]
Listagem 1 – Exemplo de uso de COUNT
begin
  --
  select 'S'
  into   vsExistNotasComFreteFOB
  from   dual
  where  exists (select 1
                 from   nota_fiscal
                 where  trunc(data) = to_date('01/04/2015') and
                        tipo_frete = 'FOB');
  --
exception
  when no_data_found then
    vsExisteNotasComFreteFOB := 'N';
end;

if vsExistNotasComFreteFOB = 'N' then
  [faça alguma coisa]
Listagem 2 – Exemplo de uso de EXISTS

 

2. Cursor com insert x Insert as select

Já encontrei construções em PL/SQL em que há um cursor por uma determinada tabela e, dentro dele, apenas um INSERT em uma outra tabela (ver Listagem 3).
Em casos como este, é mais aconselhável utilizar um INSERT AS SELECT, por ser mais rápido, já que não há a troca de contexto entre PL/SQL e SQL (ver Listagem 4).
Quando outras operações são realizadas antes do INSERT dentro do cursor, não é possível fazer a substituição.

for rCursor in (select nome,
                       endereco,
                       telefone
                from   cliente
                where  tipo_cliente = 'PJ' -- pessoa jurídica
                ) loop
  --
  insert into cliente_juridica (nome, endereco, telefone)
  values rCursor.nome, rCursor.endereco, rCursor.telefone;
  --
end loop;
Listagem 3 – Exemplo de INSERT dentro de cursor
insert into cliente_juridica (nome, endereco, telefone)
select nome,
       endereco,
       telefone
from   cliente
where  tipo_cliente = 'PJ';
Listagem 4 – Exemplo de INSERT AS SELECT

 

3. Evitar repetir SELECTs

Quando o código se torna muito extenso, é fácil se confundir e incluir 2 vezes um SELECT na mesma tabela, obtendo informações diferentes.

O problema é: o Oracle terá trabalho dobrado para obter a informação. Se esse SELECT estiver em um LOOP que executa 10 mil vezes, o SELECT será executado 20 mil vezes ao invés de apenas 10 mil, o que passa a ser muito custoso.

select nome
into   vsNome
from   cliente
where  id = vnIdCliente;
....
select endereco
into   vsEndereco
from   cliente
where  id = vnIdCliente;
Listagem 5 – Exemplo de SELECTs repetidos
select nome,
       endereco
into   vsNome,
       vsEndereco
from   cliente
where  id = vnIdCliente;
Listagem 6 – Exemplo de SELECT único

Agora você já sabe que não precisa conhecer estruturas complexas para desenvolver um sistema rápido. Você só precisa de atenção aos detalhes.

No entanto, se você quiser uma introdução a estruturas mais complexas, dê uma olhada meu post anterior (clique aqui para visualizá-lo).

Por RONALDO CHICARELI

Arquiteto de software e também apaixonado por novas culturas e idiomas, pois a vida é muito curta pra ser vivida em um só lugar.

Postado em: 30 de novembro de 2015

Confira outros artigos do nosso blog

[Webinar] Profile de aplicações Java com Oracle Mission Control e Flight Recorder

24 de julho de 2017

Danival Calegari

Criando Mocks de serviços REST com SoapUI

27 de junho de 2017

Monise Costa

Three laws that enable agile software development

09 de março de 2017

Celso Gonçalves Junior

Medindo performance de uma API REST

21 de fevereiro de 2017

Monise Costa

Deixe seu comentário