domingo, 7 de julho de 2013

DBA - Usando BIND Variable para ganhar performance



Bom dia DBA's,

Está mais do que provado que há ganhos de performance quando você utiliza Bind Variables em instruções SQL no Oracle. No artigo de hoje, vou demonstrar isso na prática e disponibilizar os comandos para que você também faça o teste em seu ambiente de estudo.

Vamos colocar a mão na massa!

Primeiro, o que é Bind Variable?


É uma forma de evitar que o Oracle realize vários parses para uma mesma instrução executada várias vezes. É a prática de criar variáveis dentro do bloco PL/SQL para que seja possível utilizá-las nas instruções.

Veja um exemplo abaixo onde o objetivo é inserir 10 mil registros em uma tabela. Para isso, criei duas procedures. Uma delas utiliza Bind Variable e a outra não.

Veja o ganho de performance:

Sem utilizar Bind: Inseriu 10.000 registros em mais de 24 segundos.
Utilizando Bind: Inseriu 10.000 registros em menos de 6 segundos.

Veja na prática:

-- Criando tabela para receber os 10 mil registros
SQL> CREATE TABLE FSILVA_10MIL (CAMPO1 INT);

Tabela criada.


-- Criando procedure para inserir 10 mil registros COM bind variable
SQL> CREATE OR REPLACE PROCEDURE COM_BIND ( i IN NUMBER )
  2    AS
  3    BEGIN
  4       INSERT INTO FSILVA_10MIL VALUES (i);
  5    END;
  6  /

Procedimento criado.

-- Criando procedure para inserir 10 mil registros SEM bind variable
SQL> CREATE OR REPLACE PROCEDURE SEM_BIND ( i IN NUMBER )
  2    AS
  3    BEGIN
  4       EXECUTE IMMEDIATE 'INSERT INTO FSILVA_10MIL VALUES ('|| i ||')';
  5    END;
  6  /

Procedimento criado.

-- Configurando para o SQL*Plus retornar o tempo decorrido
SQL> SET TIMING ON;

-- Bloco PL/SQL anônimo para inserir através de um loop, os nossos 10 mil registros SEM BIND
SQL> BEGIN
  2            FOR X IN 1..10000
  3            LOOP
  4                    SEM_BIND( X );
  5            END LOOP;
  6    END;
  7  /

Procedimento PL/SQL concluído com sucesso.

Decorrido: 00:00:24.44

-- Consultando dados inseridos
SQL> select count(*) from FSILVA_10MIL;

  COUNT(*)
----------
     10000

Decorrido: 00:00:00.10

-- Deletando todos os dados da tabela
SQL> truncate table FSILVA_10MIL;

Tabela truncada.

Decorrido: 00:00:00.29
SQL> select count(*) from FSILVA_10MIL;

  COUNT(*)
----------
         0

Decorrido: 00:00:00.03

-- Bloco PL/SQL anônimo para inserir através de um loop, os nossos 10 mil registros COM BIND
SQL> BEGIN
  2            FOR X IN 1..10000
  3            LOOP
  4                    COM_BIND( X );
  5            END LOOP;
  6    END;
  7  /

Procedimento PL/SQL concluído com sucesso.

Decorrido: 00:00:05.88

SQL> select count(*) from FSILVA_10MIL;

  COUNT(*)
----------
     10000

Decorrido: 00:00:00.04

Por hoje é isso.
Até o próximo artigo.