2012-01-05 27 views
12

Tengo un oracle stored proc que necesita ser llamado desde mi programa Java. Yo había usado CallableStatement para pasar parámetros al proceso almacenado. Estoy usando el controlador fino de Oracle (configurado en el servidor de lógica web contra la entrada jndi relevante). Este proceso almacenado no tiene ningún valor de SALIDA. Este proceso almacenado acepta un valor numérico y realiza muchas actualizaciones en el DB en función del valor recibido.PreparedStatement, CallableStatement y consideraciones de rendimiento

Obtengo un objeto de conexión y luego llamo a este proceso almacenado en bucle (20 veces para pasar 20 números). Cuando llamo directamente a este proceso almacenado desde un cliente Oracle, la ejecución se completa en 2-3 segundos. Sin embargo, el comportamiento no es predecible desde mi código java. Algunas de las llamadas tardan entre 30 y 40 segundos en completarse.

Intenté usar PreparedStatement en lugar de CallableStatement y pude ver una mejora marginal en el rendimiento (aunque el comportamiento sigue siendo inconsistente).

  1. ¿Está bien en mi caso de usar PreparedStatement en lugar de CallableStatement dado que el storedproc no tiene ningún parámetro OUT?
  2. ¿Hay alguna razón por la que PreparedStatement tenga alguna ganancia de rendimiento superior a CallableStatement o es algo que podría haber observado de forma incorrecta?
  3. ¿Existe un mejor enfoque para resolver este problema de rendimiento?
+3

¿Se puede publicar el código? Alternativamente, confirme que su conexión no se establece con cada iteración (en lugar de usar una conexión repetidamente), y confirme que no está llamando 'conn.prepareCall()' con cada iteración (en lugar de tener '.setInt () 'y' .execute() 'en el bucle). – Matt

+1

Llamas a tu procedimiento almacenado más de una vez, ¿correcto? ¿Has intentado usar llamadas por lotes? http://docs.oracle.com/javase/1.3/docs/guide/jdbc/getstart/callablestatement.html ver 7.1.3 –

+1

En lugar de realizar 20 llamadas, ¿por qué no probar un bloque anónimo de PL/SQL (comenzar ... call proc ... call proc ...... end;) que llama al proceso almacenado 20 veces y hace una llamada a la base de datos con el bloque anónimo. – GriffeyDog

Respuesta

8

Según su comentario, tiene prepareCall dentro de su ciclo. Una ventaja de las declaraciones preparadas (y las declaraciones invocables) es que puede prepararla una vez y luego intercambiar los valores pasados ​​en los parámetros; hay gastos generales cada vez que se prepara la llamada, por lo que si puede sacar eso de su ciclo, es posible que el tiempo de ejecución disminuya. Puede encontrar que desactivar Autocommit también ayuda, ya que hay sobrecarga con cada confirmación.

conn.setAutoCommit(false); 
CallableStatement stmt = conn.prepareCall(sql); 
while(true) { 
    stmt.setInt(1, value); 
    stmt.execute(); 
} 
conn.commit(); 
conn.setAutoCommit(true); 

(conn.setAutoCommit(true) lo compromete, pero me resulta más claro sea explícita).

+0

Gracias Matt. Lo entiendo mucho mejor, estoy seguro de que esto solucionará mi problema Problema. Probaré esto y la sugerencia de Sergio. Apreciar tu tiempo y ayuda :) –

+0

Hola, Matt: probé los enfoques sugeridos por ti y por Sergio, pero aún es lento cuando se realiza a través de mi código java. –

+0

Actualización: Supongo que el procedimiento en sí mismo es muy lento ahora, cuando intenté acceder al procedimiento directamente usando mi cliente Oracle - tarda aproximadamente 2 minutos para cada número.Esto se comporta de manera diferente durante diferentes momentos del día y es algo que necesito investigar. Gracias por toda tu ayuda. –

1

¿No deberías considerar usar lotes?

conn.setAutoCommit(false); 
CallableStatement stmt = conn.prepareCall(sql); 
while(true) { 
    stmt.setInt(1, value); 
    stmt.addBatch(); 
} 
stmt.executeBatch() 
conn.commit(); 
Cuestiones relacionadas