Seções iMasters
Oracle

Otimizando os comandos condicionais em Oracle

Olá pessoal, tudo bem com vocês?

Neste artigo vou demonstrar como utilizar o recurso de Short-Circuit, para tornar as condicionais dos códigos mais eficientes.

A maiorias das linguagens de programação suportam este recurso, que propõe que, quando aplicada mais de uma condição em uma cláusula de decisão, assim que a primeira seja atendida, as próximas são descartadas.

Por exemplo:

  DECLARE
v_numero INTEGER := 100;
BEGIN

IF (v_numero > 0) AND (v_numero / 2) = 0 THEN
DBMS_OUTPUT.PUT_LINE('A Divisão resulta um valor par positivo');
END IF;
END;

Veja acima que, para ser visualizada a mensagem, as duas condições devem ser satisfeitas. Caso a primeira condição não seja satisfatória (v_numero > 0), o Oracle não verifica a segunda condição ((v_numero / 2) = 0).

Podemos utilizar isso ao favor do desempenho da aplicação. Abaixo, vamos montar o cenário para efetuarmos os testes de desempenho.   

01. Crie a estrutura da tabela onde serão inseridos os movimentos ocorridos no estoque.

create table TB_MOVIMENTO
(
  ID_MOVIMENTO    NUMBER primary key,
  DT_MOVIMENTO    DATE,
  QTD_MOVIMENTADA NUMBER(4),
  COD_ITEM        VARCHAR2(6)
);

02. Iremos incluir algumas movimentações de estoque algo em torno de 10 mihões registros, que serão geradas aleatoriamente, para isso utilizarei a package dbms_random, esta proveniente da própria instalação do banco de dados.

declare
v_dt dbms_sql.date_Table; --Cria vetor do tipo data
v_qtd dbms_sql.Number_Table; --Cria vetor do tipo numérico
v_qtd_registro NUMBER := 10000000; --Quantidade de registro
begin


--Gera os registro de data de movimento em um dia.
for dd in 1..v_qtd_registro loop

v_dt(dd) := SYSDATE - dbms_random.value(1,365);

end loop;

--Termina o processo
dbms_random.terminate;

--Popular as datas geradas aleatoriamente
dbms_random.seed(99999);

--Gera os registros de quantidade movimentada
for dd in 1..v_qtd_registro loop
v_qtd(dd) := dbms_random.value(1,100);
end loop;


for dd in 1..v_dt.count loop

--Insere as movimentações
insert into tb_movimento
(id_movimento, dt_movimento, qtd_movimentada, cod_item)
values
(dd, v_dt(dd), v_qtd(dd), 'CDROM');

IF(dd/500 = 0)THEN

COMMIT;

END IF;

end loop;

commit;
end;

Após criada nossa estrutura, vamos efetuar os testes.

Em nosso cenário, o programa deve listar se a quantidade de movimentações ocorridas no mês 06 é maior que 10 mil registros. Para contar esses registros utilizarei uma função.

Primeiramente, vamos fazer do modo mais lento, colocaremos a clausula que demanda mais tempo em primeiro no IF.

SQL> DECLARE

FUNCTION FNC_QTD_MES(P_MES IN VARCHAR2) RETURN NUMBER IS
V_QTD NUMBER;
BEGIN
SELECT COUNT(*)
INTO V_QTD
FROM TB_MOVIMENTO
WHERE TO_CHAR(DT_MOVIMENTO, 'mm') = P_MES;

RETURN V_QTD;

END FNC_QTD_MES;

BEGIN

IF (FNC_QTD_MES(TO_CHAR(SYSDATE, 'mm')) > 10000 AND
TO_CHAR(SYSDATE, 'mm') = '06') THEN

DBMS_OUTPUT.PUT_LINE(A => 'A quantidade de movimentos para o mês 6 é superior à 10 mil registros!');

END IF;

END;
/

PL/SQL procedure successfully completed in 19.391 seconds

Veja que acima, sempre a função será chamada para o determinar se a condição é verdadeira em todas as execuções do processo. Caso a função retorne mais de 10 mil, a próxima clausula também será verificada.

Podemos ganhar em performace se invertemos as clausulas. Assim, primeiramente será verificado se o mês corrente é Junho, caso não seja, não será executada a função.

SQL> DECLARE

FUNCTION FNC_QTD_MES(P_MES IN VARCHAR2) RETURN NUMBER IS
V_QTD NUMBER;
BEGIN
SELECT COUNT(*)
INTO V_QTD
FROM TB_MOVIMENTO
WHERE TO_CHAR(DT_MOVIMENTO, 'mm') = P_MES;

RETURN V_QTD;

END FNC_QTD_MES;

BEGIN

IF (TO_CHAR(SYSDATE, 'mm') = '06' AND FNC_QTD_MES(TO_CHAR(SYSDATE, 'mm')) > 10000) THEN

DBMS_OUTPUT.PUT_LINE(A => 'A quantidade de movimentos para o mês 6 é superior à 10 mil registros!');

END IF;

END;
/

PL/SQL procedure successfully completed in 0 seconds

Após inverter a condição, verificando primeiro se a data de execução do processo é o Mês Junho, ganhamos baixamos o tempo de 19 segundos para 0 segundo.

Conclusão

Veja que aquela máxima de a ordem dos fatores não altera o resultado não é plenamente verdade para as condicionais. Claro que existe re-salvas, mas colocar primeiramente as clausulas de menor tempo de execução, pode ajudar com o desempenho do processo.

Abraços,

Leonardo Litz

é formado em Análise de Sistemas pela Uniban. Possui 10 anos de experiência em análise, implementação e desenvolvimento de softwares com Oracle Forms/Reports, PL/SQL. Também possui experiência de 6 anos em WebTool Kit, HTML, JavaScript, XML, CSS e APEX, além de conhecimentos em JAVA e Delphi. Possui certificação Oracle Advanced PL/SQL Developer Certified Professional 11g. Em sua experiência profissional teve a oportunidade de participar de diversos projetos, dos quais pode-se destacar migrações de sistemas de arquivos indexados em Cobol para banco de dados Oracle; tunning em camada de aplicações e camada de banco de dados; administração de banco de dados Oracle 9i e 10g; modelagem relacional de dados utilizando Erwin; migração do Forms 6i para Forms IAS 10g; levantamento, análise e desenvolvimento de software em Delphi com Oracle, Oracle WebTool Kit e APEX. Atualmente trabalha em uma empresa petroquimica, na qual atua como Desenvolvedor Oracle EBS, desenvolvendo customizações para todos os módulos, nos padrões e recursos do ERP, utilizando PL/Sql, Forms 6i, Reports 6i, Discover, WorkFlow e APEX.

Email
Comente também

6 Comentários

Boa tarde, excelente texto, prático e direto. Só tenho talvez uma correção.

“assim que a primeira seja atendida, as próximas são descartadas.”
não seria
“assim que a primeira não for atendida, as próximas são descartadas.”

Abraço.

    Primeiramente obrigado Cleiton.
    Exatamente, houve um pequeno erro, já estou pedindo a correção.
    Muito obrigado pelo Observação.

José Mario Barduchi

Fala Leonardo…

Muito legal o artigo.. Simples, direto e objetivo…

Muito legal…

Abraço
Mario

Muito legal, gostei!

Maurício

Parabéns pelo exemplo…
Tudo relacionado a performance acho intressante.

Leonardo Silva

Muito bom Gaúcho … Parabéns meu irmão.

Qual a sua opinião?