stored procedures kj hn uyg n uyg ny tfn yut fnu ytf u ytf uyt f uyt fu ytf y tg u yg uyh biu h inu...

3
Grupo de Usuários Java http://www.guj.com.br) Nem sempre use stored procedures Artur Saccaro Um exemplo de situação em que não utilizar uma stored procedure aumentou muito a eficiência da aplicação Situação inicial A alguns dias me deparei com uma determinada situação em que precisava fazer um Select e dois Inserts em uma base de dados Oracle para cada elemento de um ArrayList dado. Sendo esta uma operação parecida com uma funcionalidade antiga da aplicação, decidi utilizar o mesmo método: uma Stored Procedure já presente na aplicação. Código da Stored Procedure “insere” create or replace procedure insere(param1 number, param2 varchar2, param3 varchar2, param4 varchar2) is constante number; begin select resultado.nextval into results from dual; insert into tabela1 (campo1, campo2) values(resultado, param2); if(param1 = 1) then insert into tabela2(campo1, campo2) values(param3, param4); else insert into tabela3 (campo1, campo2, campo3) values(param2, param3, param4); end if; end insere; Trecho de código da primeira solução implementada em Java, utilizando a Stored Procedure: String sql = "call insere(?, ?, ?, ?)"; Connection con = ConnectionBroker.getConnection(); PreparedStatement st = con.prepareStatement(sql); Iterator iter = arrayList.iterator() while(iter.hasNext()){ objeto = (Objeto) iter.next(); st.setInt (1, objeto.getPropriedade1()); st.setString(2, objeto.getProperiedade2()); st.setString(3, objeto.getProperiedade3()); st.setString(4, objeto.getProperiedade4()); st.execute(); } A stored procedure “insere” faz um select cujo resultado é utilizado em um insert em uma dada tabela e um outro insert em outra tabela definida pelo primeiro parâmetro da procedure “insere”. O processo todo levava aproximadamente UMA HORA para ser concluído quando aplicado em um ArrayList de 5000 elementos. Testes e a solução Inconformado com este resultado, preparei um teste com um script para 10000 Inserts nas mesmas tabelas, apenas para comparação. Rodando o script diretamente na ferramenta SQLPlus da Oracle, sem nenhuma interferência do Java, a operação levou menos de TRÊS MINUTOS. Como, infelizmente, esta stored procedure vinha como legado do sistema (o que me impedia de modificá-la), tentei uma saida menos elegante mas ainda assim mais eficiente: ignorar a procedure Grupo de Usuários Java – http://www.guj.com.br – Página 1

Upload: alessandro-oliveira

Post on 02-Dec-2015

226 views

Category:

Documents


0 download

DESCRIPTION

Stored Procedures. dsfsf sd sdf sd f sdf ds fsdfsdf sdf we f wef sd fs ef sdf sd fds g dgsb xshgn hgdn ghn ynt n dytn td yn ty h ytd hh fdh fd hf h fdh ft hrs hg sh rt hr sh rth rsh srhrtiuhgiuvho iunh niuy gfn iytf ny tfn uiyt fnu ytfvnbiuytfniuyt vniyu tvn iuyt vn yiutnuy tv nuyt vn iytv nuy tv niuyt vn yutv niuy tv nyut vn uytv nuy tvn yut vnn uytv u ytvn uy tv uytv niu yb ui hbniou yb miu yb iuy bm iuyb miu yb muy b nyt vn uytv nbuyt vn uyt vb uytv buty fb utrfbu ytf bniy gj miuy hjm uh moiu hn oiuy gn iu tf nuy tf buyt fb iytf ni ytg i uyg iou yg niu ygn iuy gni ytf nuy tf buyt fb uytf biuy tf ib ty fb iyt fbiuy tfb uyt fbu ytf buty fb uytfb uyt f

TRANSCRIPT

Page 1: Stored Procedures kj hn uyg n uyg ny tfn yut fnu ytf u ytf uyt f uyt fu ytf y tg u yg uyh biu h inu hin uhg iu h

Grupo de Usuários Java http://www.guj.com.br)

Nem sempre use stored procedures

Artur Saccaro

Um exemplo de situação em que não utilizar uma stored procedure aumentou muito a eficiência da aplicação

Situação inicial A alguns dias me deparei com uma determinada situação em que precisava fazer um Select e dois

Inserts em uma base de dados Oracle para cada elemento de um ArrayList dado. Sendo esta uma operação parecida com uma funcionalidade antiga da aplicação, decidi utilizar o mesmo método: uma Stored Procedure já presente na aplicação.

Código da Stored Procedure “insere”

create or replace procedure insere(param1 number, param2 varchar2, param3 varchar2, param4 varchar2) is constante number; begin select resultado.nextval into results from dual; insert into tabela1 (campo1, campo2) values(resultado, param2); if(param1 = 1) then insert into tabela2(campo1, campo2) values(param3, param4); else insert into tabela3 (campo1, campo2, campo3) values(param2, param3, param4); end if; end insere;

Trecho de código da primeira solução implementada em Java, utilizando a Stored Procedure:

String sql = "call insere(?, ?, ?, ?)"; Connection con = ConnectionBroker.getConnection(); PreparedStatement st = con.prepareStatement(sql); Iterator iter = arrayList.iterator() while(iter.hasNext()){ objeto = (Objeto) iter.next(); st.setInt (1, objeto.getPropriedade1()); st.setString(2, objeto.getProperiedade2()); st.setString(3, objeto.getProperiedade3()); st.setString(4, objeto.getProperiedade4()); st.execute(); }

A stored procedure “insere” faz um select cujo resultado é utilizado em um insert em uma dada tabela e um outro insert em outra tabela definida pelo primeiro parâmetro da procedure “insere”.

O processo todo levava aproximadamente UMA HORA para ser concluído quando aplicado em um

ArrayList de 5000 elementos.

Testes e a solução Inconformado com este resultado, preparei um teste com um script para 10000 Inserts nas mesmas

tabelas, apenas para comparação. Rodando o script diretamente na ferramenta SQLPlus da Oracle, sem nenhuma interferência do Java, a operação levou menos de TRÊS MINUTOS.

Como, infelizmente, esta stored procedure vinha como legado do sistema (o que me impedia de

modificá-la), tentei uma saida menos elegante mas ainda assim mais eficiente: ignorar a procedure

Grupo de Usuários Java – http://www.guj.com.br – Página 1

Page 2: Stored Procedures kj hn uyg n uyg ny tfn yut fnu ytf u ytf uyt f uyt fu ytf y tg u yg uyh biu h inu hin uhg iu h

Grupo de Usuários Java http://www.guj.com.br)

E assim ficou o código Java:

String sql = null; Connection con = null; PreparedStatement st = null; ResultSet rs = null; int status = 0; Iterator iter = arrayList.iterator() while(iter.hasNext()){ objeto = (Objeto) iter.next(); // ConnectionBroker retorna uma conexão obtida usando o pool de conexões Oracle con = ConnectionBroker.getConnection(); //Seleciona um valor da tabela 0 para definir em qual tabela fazer o insert sql = "select status from tabela0"; st = con.prepareStatement(sql); rs = st.executeQuery(); if(rs.next()){ status = rs.getInt(“status”); } rs.close(); st.close(); con.close(); con = ConnectionBroker.getConnection(); // Insere alguns campos na tabela 1 sql = "insert into tabela1 (campo1, campo2) values(?, ?)"; st = con.prepareStatement(sql); st.setString(1, status); st.setString(2, objeto.getProperiedade1()); st.execute(); st.close(); con.close(); // define qual insert fazer a partir do valor selecionado na tabela 0 if(status == 1){ con = ConnectionBroker.getConnection(); sql = "insert into tabela2 (campo1, campo2) values(?, ?)"; st = con.prepareStatement(sql); st.setString(1, objeto.getProperiedade3()); st.setString(2, objeto.getProperiedade4()); st.executeUpdate(); st.close(); con.close(); }else{ con = ConnectionBroker.getConnection(); sql = "insert into tabela3 (campo1, campo2, campo3) values(?, ?)"; st = con.prepareStatement(sql); st.setString(1, objeto.getProperiedade2()); st.setString(2, objeto.getProperiedade3()); st.setString(2, objeto.getProperiedade4()); st.execute(); st.close(); con.close(); } }

Esta solução praticamente traduz a procedure do Oracle para um método Java e mesmo refazendo 3

vezes as conexões e os PreparedStatements a cada passagem do while, o processo todo levou pouco mais de QUATRO MINUTOS para os mesmos 5000 elementos do ArrayList.

Este procedimento poderia ainda ser otimizado, uma vez que foi escrito de forma muito rápida, mas o resultado já trouxe um ganho mais que satisfatório para as necessidades da aplicação.

Grupo de Usuários Java – http://www.guj.com.br – Página 2

Page 3: Stored Procedures kj hn uyg n uyg ny tfn yut fnu ytf u ytf uyt f uyt fu ytf y tg u yg uyh biu h inu hin uhg iu h

Grupo de Usuários Java http://www.guj.com.br)

Comparativo do tempo consumido pelas operações

0

10

20

30

40

50

60

70

Com a Stored Procedure Com o script pelo SQL Plus Sem a Stored Procedure

Conclusão Eu não sou contra o uso de Triggers, Stored Procedures ou Functions (embora elas possam tornar a

aplicação mais dependente do Banco de Dados), mas já vi muitos casos em que estas funcionalidades foram utilizadas apenas por "conveniência" e, principalmente, não foram analizadas por um bom DBA. O que eu quero dizer é que as funcionalidades de um bom SGBD podem fazer a sua aplicação voar mas, se não forem bem utilizadas, não trazem o ganho de performance esperado.

Artur Saccaro ([email protected]) é desenvolvedor Java e trabalha na People Consulting desenvolvendo aplicações J2EE com a framework Struts e banco de dados Oracle.

Grupo de Usuários Java – http://www.guj.com.br – Página 3