JDBCTemplate de Spring Lenta

Buen día,

Les comento que una aplicación esta heredando la clase StoredProcedure de Spring 2.5 y mediante la llamada de

super.execute( map );

Donde "map" es un HashMap con los parámetros de entrada de una función de oracle.

Estoy tomando el tiempo de ejecución de las funciones que se invocan y el código es simplemente,

long timeInicial=System.currentTimeMillis( );
outputParametersMap=super.execute( map );
long timeFinal=System.currentTimeMillis();

La sorpresa comienza cuando comenzamos a ver que había funciones de BD que tardan supuestamente 5, 8 o hasta 15 segundos, lo que en un inicio, pensamos que había que optimizar las funciones, pero después de una larga historia, pense que lo mejor sería medir el tiempo de ejecució directamente desde donde Spring invoca realmente a la función, así que descargue el código fuente de Spring 2.5.6 y después de revisar lo que hace el método execute de la clase StoredProcedure, me doy cuenta que entre algunas cosas más, a final de cuentas llama al método "call" de la clase JDBCTemplate.

El método "call" hace algunas cosas antes de invocar la función y finalmente la invoca:

 boolean retVal = cs.execute();

donde "cs" es un CallableStatement del paquete java.sql

En la línea anterior es donde comence a tomar el tiempo de ejecución,

long tInicial = System.currentTimeMillis();
boolean retVal = cs.execute();
long tFinal = System.currentTimeMillis();

Para mi sorpresa, el tiempon de ejecución tomado desde la mismisima clase JDBCTemplate es sencillamente muy rápido comparado que si tomo el tiempo desde la aplicación web.

¿Cual es el problema?

Que sencillamente después de ejecutar las líneas anteriores´y algunas otras más, existe esta línea,

returnedResults.putAll(extractOutputParameters(cs, callParameters));

¿Que pasa con ella?... Que es la que esta consumiendo el mayor tiempo de ejecución.

Al tomar el tiempo aqui

long tInicial = System.currentTimeMillis();
boolean retVal = cs.execute();
long tFinal = System.currentTimeMillis();

Se obtiene una ejecución de 156 milisegundos!! Y es donde entiendo se llama realmente a la función de BD.

Sin embargo, cuando tomo el tiempo de ejecución de la llamada a la siguiente línea,

returnedResults.putAll(extractOutputParameters(cs, callParameters));

Obtengo que tarda 6297 milisegundos!!!!!!

Por esta razón, es que cuando tomaba el tiempo desde la aplicación web, me arrojaba un tiempo de ejecución que no es real pero al tomar el tiempo de ejecución desde la misma clase de Spring me doy cuenta que en realidad la llamada a la función es muy rápida, pero lo que esta tardando es la ejecución de

returnedResults.putAll(extractOutputParameters(cs, callParameters));

¿Que pasará? ¿El método extractOutputParameters no será muy óptimo? ¿Alguna sugerencia?

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

Spring 3

Y si pruebas con JdbcTemplate pero de Spring 3? Tal vez tenga mejor rendimiento. Ese método seguramente tiene que tomar en cuenta mil casos distintos y por tanto es bastante general, puede que tu caso particular de stored procedure le cause problemas al componente de Spring, pero 6 segundos??? Si ejecutas el SP directo en Oracle con los mismos datos supongo que no se tarda 6 segundos...

Imagen de WinDoctor

En efecto

Así es, si ejecutamos la función por ejemplo desde el TOAD, obtengo tiempos similares, 296 milisegundos por ejemplo.

La aplicación se encuentra ya productiva... En tu experiencia, crees que tenga algún impacto o migrar a Spring 3 sea complicado¿?

Lo que voy a intentar es con el código fuente que baje, crear una conexión a la BD y hacer debugg al código de dicho método para ver en que casos if esta cayendo y en donde específicamente tarda.

Saludos!

Imagen de ezamudio

modulos

Yo uso Spring desde la versión 1.0, y los cambios a la 2 estuvieron fuertes por la introducción de generics y soporte para Java 5. Luego creo que fue de la 2 a la 2.5 donde partieron el megaframework en módulos y ahí el rollo principal fue sabes cuáles necesitabas. Pero de la 2.5 a la 3.0 estuvo leve, creo que lo más enredoso fue actualizar a usar algunas clases e interfaces nuevas en vez de algunas deprecadas; por ejemplo si empezaste a usar SimpleJdbcTemplate de Spring 2.5, en Spring 3 ya es nuevamente JdbcTemplate nada más (el viejo JdbcTemplate ya se fue a volar). ParameterizedRowMapper igual se fue a volar y ahora es nuevamente sólo RowMapper, etc.