El proceso almacenado se ejecuta un 30% más lento a través de Java en lugar de ejecutarse directamente en la base de datos

Estoy usando Java 1.6, JTDS 1.2.2 (también probé 1.2.4 sin ningún resultado) y SQL Server 2005 para crear un CallableStatement para ejecutar un procedimiento almacenado (sin parámetros). Estoy viendo que el contenedor Java ejecuta el mismo procedimiento almacenado un 30% más lento que usando SQL Server Management Studio. He ejecutado el perfilador de MS SQL y hay poca diferencia en la E / S entre los dos procesos, por lo que no creo que esté relacionado con el almacenamiento en caché del plan de consulta.

El proceso almacenado no toma argumentos y no devuelve datos. Utiliza un cursor del lado del servidor para calcular los valores necesarios para rellenar una tabla.

No puedo ver cómo la llamada a un proceso almacenado desde Java debería agregar una sobrecarga del 30%, seguramente es solo un conducto a la base de datos que el SQL se envía y luego la base de datos lo ejecuta ... ¿Podría la base de datos estar dando la Java? aplicación un plan de consulta diferente?

He publicado en amboslos foros de MSDN, y los foros JTDS de sourceforge (tema: "el proceso almacenado es más lento en JTDS que el directo en DB") Me preguntaba si alguien tiene alguna sugerencia de por qué esto podría estar sucediendo.

Gracias por adelantado,

-James

(N.B. No temas, recopilaré las respuestas que obtengamos en otros foros aquí cuando encuentre la solución)

Fragmento de código Java:

sLogger.info("Preparing call...");
stmt = mCon.prepareCall("SP_WB200_POPULATE_TABLE_limited_rows");
sLogger.info("Call prepared.  Executing procedure...");
stmt.executeQuery();
sLogger.info("Procedure complete.");

He ejecutado el perfil de SQL y he encontrado lo siguiente:

Aplicación Java: CPU: 466,514 Lecturas: 142,478,387 Escrituras: 284,078 Duración: 983,796

SSMS: CPU: 466,973 Lecturas: 142,440,401 Escrituras: 280,244 Duración: 769,851

(Ambos con DBCC DROPCLEANBUFFERS se ejecutan antes del perfilado, y ambos producen el número correcto de filas)

Así que mi conclusión es que ambos ejecutan las mismas lecturas y escrituras, es solo que la forma en que lo están haciendo es diferente, ¿qué piensan ustedes?

Resulta que los planes de consulta son significativamente diferentes para los diferentes clientes (el cliente Java está actualizando un índice durante una inserción que no está en el cliente SQL más rápido, además, la forma en que está ejecutando uniones es diferente (los bucles anidados Vs. recopilar secuencias, bucles anidados Vs exploraciones de índice, argh!)). Bastante por qué esto es, todavía no lo sé (volveré a publicarlo cuando llegue al fondo)

Epílogo

No pude hacer que esto funcione correctamente. Intenté homogeneizar las propiedades de conexión (arithabort, ansi_nulls etc) entre los clientes de estudio de Java y Mgmt. Al final, los dos clientes diferentes tenían planes de consulta / ejecución muy similares (pero aún con diferentes plan_ids reales). Publiqué un resumen de lo que encontrélos foros de MSDN SQL Server Como encontré un rendimiento diferente no solo entre un cliente JDBC y un estudio de administración, sino también entre el propio cliente de línea de comandos de Microsoft, SQLCMD, también verifiqué algunas cosas más radicales como el tráfico de red, o envolviendo el proceso almacenado dentro de otro proceso almacenado, solo para sonríe

Tengo la sensación de que el problema radica en algún lugar en la forma en que se ejecutaba el cursor, y de alguna manera estaba dando lugar a la suspensión del proceso de Java, pero ¿por qué un cliente diferente debería dar lugar a este comportamiento diferente de bloqueo / espera cuando no se está ejecutando nada más? y el mismo plan de ejecución está en operación está un poco más allá de mis habilidades (¡no soy DBA!).

Como resultado, he decidido que 4 días es suficiente para que cualquiera pueda perder el tiempo en algo como esto, así que codificaré a regañadientes a su alrededor (si soy sincero, el procedimiento almacenado necesitaba volver a codificarse para ser más incremental en lugar de re -calculando todos los datos cada semana de todos modos), y tiza este para experimentar. Dejaré la pregunta abierta, muchas gracias a todos los que pusieron su sombrero en el ring, todo fue útil, y si a alguien se le ocurre algo más, me encantaría escuchar algunas opciones más ... y si alguien encuentra Este post como resultado de ver este comportamiento en sus propios entornos, entonces, con suerte, hay algunos consejos que puede probar usted mismo, y esperamos ver más allá de lo que lo hicimos.

Estoy listo para mi fin de semana ahora!

-James

Respuestas a la pregunta(7)

Su respuesta a la pregunta