2011-08-25 15 views
15

La nostra azienda ha un'applicazione batch che viene eseguita tutti i giorni, per lo più svolge alcuni lavori relativi al database, ad esempio importa dati nella tabella del database da file.Tutorial sull'utilizzo di multi-threading in jdbc

Ci sono 20+ compiti definiti in quella applicazione, ognuno può dipendere da altri o meno. L'applicazione esegue le attività una alla volta, l'intera applicazione viene eseguita in un singolo thread.

Richiede 3 ~ 7 ore per completare tutte le attività. Penso che sia troppo lungo, quindi penso che forse posso migliorare le prestazioni con il multi-threading.

penso in quanto v'è la dipendenza tra i compiti, non va bene (o non è facile) per semplificare le attività eseguite in parallelo, ma forse posso usare il multi-threading per migliorare le prestazioni all'interno di un compito.

ad esempio: abbiamo un'attività definita come "ImportBizData", che copia i dati in una tabella di database da un file di dati (in genere contiene 100.0000+ righe). Mi chiedo se vale la pena usare il multi-threading?

Come so un po 'di multi-threading, spero che qualcuno fornisca alcuni link tutorial su questo argomento.

+1

prima, stai già utilizzando le operazioni batch JDBC? – Thilo

+0

alcune attività usano, altre no – CaiNiaoCoder

+1

Il tuo intuito è giusto che vale la pena guardare il multithreading di questo. Una volta ho convertito un lavoro batch di otto ore in un lavoro di 15-20 minuti facendo esattamente quello che stai pensando di fare. –

risposta

20

Multi-threading migliorerà le prestazioni, ma ci sono un paio di cose che dovete sapere:

  1. Ogni thread ha bisogno di una propria connessione JDBC. Le connessioni non possono essere condivise tra thread perché ogni connessione è anche una transazione.
  2. Carica i dati in blocchi e commit una volta ogni tanto per evitare di accumulare enormi tabelle di rollback/annullamento.
  3. Taglia le attività in più unità di lavoro in cui ogni unità esegue un lavoro.

Elaborare l'ultimo punto: Attualmente, si dispone di un compito che legge un file, lo analizza, apre una connessione JDBC, fa alcuni calcoli, invia i dati al database, ecc

Quello che dovrebbe fare:

  1. Uno (!) thread per leggere il file e creare "lavori" da esso. Ogni lavoro dovrebbe contenere una "unità di lavoro" piccola, ma non troppo piccola. Spingere quelli in coda
  2. Il/i thread successivo/i attende/i per i lavori in coda e esegue i calcoli. Ciò può accadere mentre i thread del passaggio n. 1 attendono che il disco rigido lento restituisca le nuove righe di dati. Il risultato di questo passaggio di conversione passa alla coda successiva
  3. Uno o più thread per caricare i dati tramite JDBC.

Il primo e l'ultimo thread sono piuttosto lenti perché sono vincolati all'I/O (gli hard disk sono lenti e le connessioni di rete sono ancora peggiori). Inoltre l'inserimento di dati in un database è un compito molto complesso (l'allocazione dello spazio, l'aggiornamento degli indici, controllando le chiavi esterne)

Utilizzando diversi thread di lavoro ti dà un sacco di vantaggi:

  1. E 'facile testare ogni thread separatamente. Dal momento che non condividono i dati, non è necessaria alcuna sincronizzazione. Le code si farà per voi
  2. È possibile modificare rapidamente il numero di thread per ogni passo per ottimizzare le prestazioni
5

Il threading multiplo può essere di aiuto, se le linee non sono correlate, è possibile avviare due processi con una sola lettura di linee, altre linee non uniformi e ottenere la connessione db da un pool di connessioni (dbcp) e analizzare le prestazioni. Ma prima vorrei indagare se jdbc è l'approccio migliore normalmente i database hanno soluzioni ottimizzate per importazioni come questa. Queste soluzioni possono anche cambiare temporaneamente il controllo dei vincoli della tabella e riaccenderlo in un secondo momento, il che è anche ottimo per le prestazioni. Come sempre in base alle tue esigenze.

Inoltre, è possibile eseguire il checkout di springbatch progettato per l'elaborazione in batch.

+0

+1 per Spring Batch. – carlspring

+0

"normalmente i database hanno soluzioni ottimizzate per importazioni come questa" sì, ma in tale compito dobbiamo fare un po 'di calcolo prima di inserire o aggiornare – CaiNiaoCoder

+0

@YAMaiDie: esportare i dati, fare i calcoli e creare un file di importazione. –

0

Per quanto ne so, il bridge JDBC utilizza metodi sincronizzati per serializzare tutte le chiamate verso ODBC, quindi l'utilizzo di thread multipli non darà alcun incremento di prestazioni a meno che non migliori l'applicazione stessa.

+2

Dove dice "ODBC"? –

+0

Oh, giusto, ho lavorato così tanto con il bridge JDBC-ODCB ultimamente che ho quasi dimenticato che ci sono anche implementazioni native dei driver :) – Tobson

0

Non sono molto familiare con JDBC ma riguardo al bit multithreading della tua domanda, quello che dovresti tenere a mente è che l'elaborazione parallela si basa sulla suddivisione efficace del tuo problema in bit indipendenti tra loro e in qualche modo mettendo loro di nuovo insieme (il loro output è). Se non conosci le dipendenze sottostanti tra le attività, potresti finire per avere errori/eccezioni davvero strani nel tuo codice. Ancora peggio, tutto potrebbe essere eseguito senza problemi, ma i risultati potrebbero essere fuori dai valori veri. Il multi-threading è un affare complicato, in un certo senso divertente da apprendere (almeno così penso), ma il dolore al collo quando le cose vanno a sud.

Qui ci sono un paio di link che potrebbe fornire utili:

Se siete seriamente di mettere sforzo per ottenere in multi-threading posso consigliare GOETZ, BRIAN: JAVA CONCURRENCY, libro fantastico davvero ..

Buona fortuna

0

Ho avuto un simile compito. Ma nel mio caso, tutti i tavoli non erano collegati tra loro.

STEP1: Utilizzo di SQL Loader (Oracle) per il caricamento di dati nel database (molto veloce) OPPURE qualsiasi strumento di aggiornamento collettivo simile per il database.

STEP2: Esecuzione di ogni processo di caricamento in un thread diverso (per attività non correlate) e in un singolo thread per attività correlate.

P.S. È possibile identificare diversi lavori correlati tra loro nella propria applicazione e categorizzarli in gruppi; e eseguendo ogni gruppo in thread diversi.

Link ad eseguire fino:

JAVA Threading seguire l'ultimo esempio nel link qui sopra (Esempio: Partizionare un grande compito con più thread)

SQL Loader can dramatically improve performance

0

Se il threading multiplo complicherebbe il tuo lavoro, potresti utilizzare la messaggistica asincrona. Non sono pienamente consapevole di quali siano i tuoi bisogni, quindi, il seguito è da ciò che sto vedendo attualmente.

  1. Creare un lettore di file java il cui scopo è leggere il file biz e inserire i messaggi nella coda JMS sul server. Questo potrebbe essere Java semplice con static void main()
  2. Consumare i messaggi JMS nei bean Message-Message (È possibile impostare il limite sul numero di bean da creare nel pool, 50 o 100 a seconda delle necessità) se hai server multipli, bene e bene, il tuo lavoro è ora diviso in più server.
    1. Ogni riga di dati viene suddivisa in modo asincrono tra 2 server e 50 bean su ciascun server.

Non avere a che fare con fili in tutto il processo, JMS è l'ideale perché i vostri dati sono all'interno di una transazione, se qualcosa non riesce prima di inviare un ACK al server, il messaggio sarà inviato nuovamente al consumatore, il carico verrà diviso tra i server senza che tu faccia nulla di speciale come il multi-threading.

Inoltre, la molla fornisce un lotto di molle che può essere d'aiuto. http://docs.spring.io/spring-batch/reference/html/spring-batch-intro.html#springBatchUsageScenarios