2011-08-25 12 views
15

Nuestra empresa tiene una aplicación por lotes que se ejecuta todos los días, realiza algunos trabajos relacionados con la base de datos en su mayoría, importar datos en la tabla de base de datos del archivo, por ejemplo.Tutorial sobre el uso de multi-threading en jdbc

Hay más de 20 tareas definidas en esa aplicación, cada una puede depender de otras o no. La aplicación ejecuta tareas una a una, toda la aplicación se ejecuta en una sola cadena.

Tarda de 3 a 7 horas en terminar todas las tareas. Creo que es demasiado largo, por lo que creo que tal vez pueda mejorar el rendimiento mediante multi-threading.

Creo que como hay dependencia entre las tareas, no es bueno (o no es fácil) hacer que las tareas se ejecuten en paralelo, pero tal vez pueda usar multi-threading para mejorar el rendimiento dentro de una tarea.

por ejemplo: tenemos una tarea definida como "ImportBizData", que copia los datos en una tabla de base de datos desde un archivo de datos (generalmente contiene 100,0000 filas). Me pregunto si vale la pena usar multi-threading?

Como sé un poco acerca de multi-threading, espero que alguien proporcione algunos enlaces de tutoriales sobre este tema.

+1

antes de eso, ¿ya está utilizando las operaciones por lotes JDBC? – Thilo

+0

uso de algunas tareas, algunas no – CaiNiaoCoder

+1

Su intuición es correcta, vale la pena considerar esto como multithreading. Una vez convertí un trabajo por lotes de ocho horas en un trabajo de 15-20 minutos haciendo exactamente lo que estás pensando en hacer. –

Respuesta

20

multi-threading va a mejorar su rendimiento, pero hay un par de cosas que usted necesita saber:

  1. Cada hilo necesita su propia conexión JDBC. Las conexiones no se pueden compartir entre subprocesos porque cada conexión también es una transacción.
  2. Cargue los datos en fragmentos y commit de vez en cuando para evitar la acumulación de enormes tablas de deshacer/deshacer.
  3. Corte las tareas en varias unidades de trabajo donde cada unidad realiza un trabajo.

para elaborar el último punto: En la actualidad, tiene una tarea que lee un archivo, lo analiza, se abre una conexión JDBC, hace algunos cálculos, envía los datos a la base de datos, etc.

Lo que debería hacer:

  1. Un (!) hilo para leer el archivo y crear "trabajos" de él. Cada trabajo debe contener una "unidad de trabajo" pequeña pero no demasiado pequeña. Inserte ésos en una cola
  2. La (s) próxima (s) cadena (s) espera (s) para trabajos en la cola y realiza los cálculos. Esto puede suceder mientras los subprocesos del paso n. ° 1 esperan a que el disco duro lento devuelva las nuevas líneas de datos. El resultado de este paso de conversión pasa a la siguiente cola
  3. Uno o más subprocesos para cargar los datos a través de JDBC.

El primer y el último subprocesos son bastante lentos porque están vinculados con E/S (los discos duros son lentos y las conexiones de red son aún peores). Además de la inserción de datos en una base de datos es una tarea muy compleja (la asignación de espacio, actualizar índices, comprobando las claves externas)

Utilizando diferentes subprocesos de trabajo le da un montón de ventajas:

  1. Es fácil de probar cada hilo por separado. Como no comparten datos, no necesita sincronización. Las colas van a hacer eso para usted
  2. Puede cambiar rápidamente el número de hilos por cada paso para ajustar el rendimiento
5

El subprocesamiento múltiple puede ser útil, si las líneas no están correlacionadas, puede iniciar dos procesos, una lectura de líneas pares, otras líneas desiguales, obtener su conexión db desde un conjunto de conexiones (dbcp) y analizar el rendimiento. Pero primero investigaría si jdbc es el mejor enfoque que normalmente las bases de datos tienen soluciones optimizadas para importaciones como esta. Estas soluciones también pueden cambiar temporalmente la comprobación de restricciones de su tabla y volver a activarla más tarde, lo que también es excelente para el rendimiento. Como siempre dependiendo de tus requerimientos.

También es posible que desee retirar el springbatch que está diseñado para el procesamiento por lotes.

+0

+1 para Spring Batch. – carlspring

+0

"normalmente las bases de datos tienen soluciones optimizadas para importaciones como esta" sí, pero en esa tarea tenemos que hacer algunos cálculos antes de insertar o actualizar – CaiNiaoCoder

+0

@YAMaiDie: Exporte los datos, haga los cálculos y cree un archivo de importación. –

0

Hasta donde yo sé, el puente JDBC utiliza métodos sincronizados para serializar todas las llamadas a ODBC, por lo que usar hilos mutliple no le dará ningún aumento de rendimiento a menos que aumente su aplicación.

+2

¿Dónde dice "ODBC"? –

+0

Ah, claro, he estado trabajando tanto con el puente JDBC-ODCB últimamente que casi olvidé que también hay implementaciones de controladores nativos :) – Tobson

0

No estoy muy familiarizado con JDBC, pero con respecto al bit multithreading de su pregunta, lo que debe tener en cuenta es que el procesamiento paralelo se basa en dividir efectivamente su problema en bits independientes y de alguna manera poner ellos de nuevo juntos (su resultado es). Si no conoce las dependencias subyacentes entre las tareas, puede terminar teniendo errores/excepciones realmente extrañas en su código. Peor aún, podría ejecutarse sin problemas, pero los resultados podrían estar fuera de los valores reales. Multi-threading es un negocio difícil, de una manera divertida de aprender (al menos eso creo) pero un dolor en el cuello cuando las cosas van hacia el sur.

Aquí hay un par de enlaces que pueden proporcionar útil:

Si usted es serio acerca de poner esfuerzo para conseguir en multi-threading puedo recomendar GOETZ, BRIAN: JAVA CONCURRENCY, libro increíble realmente ...

Buena suerte

0

que tenía una tarea similar . Pero en mi caso, todas las tablas no estaban relacionadas entre sí.

PASO 1: Uso de SQL Loader (Oracle) para cargar datos en la base de datos (muy rápido) O cualquier herramienta de actualización masiva similar para su base de datos.

PASO 2: Ejecución de cada proceso de carga en un subproceso diferente (para tareas no relacionadas) y en un solo subproceso para las tareas relacionadas.

P.S. Puede identificar diferentes trabajos interrelacionados en su aplicación y categorizarlos en grupos; y ejecutar cada grupo en diferentes hilos.

Enlaces a ejecutar hasta:

JAVA Threading siguen el último ejemplo en el enlace anterior (Ejemplo: Partición de una gran tarea con múltiples hilos)

SQL Loader can dramatically improve performance

0

Si Multithreading podría complicar su trabajo, podría ir con la mensajería Async. No estoy completamente enterado de cuáles son sus necesidades, entonces, lo siguiente es de lo que estoy viendo actualmente.

  1. Crea un lector de archivos java cuyo propósito es leer el archivo biz y colocar mensajes en la cola JMS en el servidor. Esto podría ser Java simple con static void main()
  2. Consumir los mensajes JMS en los beans controlados por mensaje (Puede establecer el límite de la cantidad de beans que se crearán en el grupo, 50 o 100 dependiendo de la necesidad) tiene servidores múltiples, está bien, su trabajo ahora está dividido en varios servidores.
    1. Cada fila de datos se divide de forma asincrónica entre 2 servidores y 50 beans en cada servidor.

Usted no tiene que lidiar con las discusiones en todo el proceso, JMS es ideal, ya que sus datos están dentro de una transacción, si algo falla antes de enviar un acuse de recibo al servidor, el mensaje será reenviado para el consumidor, la carga se dividirá entre los servidores sin que usted haga algo especial, como el multi-threading.

Además, spring proporciona lotes de muelles que pueden ayudarlo. http://docs.spring.io/spring-batch/reference/html/spring-batch-intro.html#springBatchUsageScenarios

Cuestiones relacionadas