Oracle
 sql >> Database >  >> RDS >> Oracle

Lettura database multi threading

Rete

Prima di tutto, dall'utilizzo di rowid e rownum è comunque vendor-lock, dovresti considerare l'utilizzo di routine memorizzate nel database. Potrebbe ridurre significativamente l'overhead di trasmissione dei dati dal database al server delle applicazioni (soprattutto se si trovano su macchine diverse e connesse tramite rete).

Considerando che hai 80 milioni di record da trasmettere, questo potrebbe essere il miglior miglioramento delle prestazioni per te, anche se dipende dal tipo di lavoro svolto dai tuoi thread.

Ovviamente aumentare la larghezza di banda aiuterebbe anche a risolvere i problemi di rete.

Prestazioni del disco

Prima di apportare modifiche al codice, controlla il carico del disco rigido durante l'esecuzione delle attività, forse non è in grado di gestire così tanto I/O (lettura simultanea di 10 thread).

La migrazione a SSD/RAID o al database di clustering potrebbe risolvere il problema. Durante la modifica del modo in cui accedi al database non lo farà in quel caso.

Il multithreading potrebbe risolvere i problemi della CPU, ma i database dipendono principalmente dal sistema del disco.

Rownum

Ci sono un paio di problemi che potresti incontrare se lo implementerai utilizzando rowid e rownum.

1) rownum viene generato al volo per i risultati di ogni query. Quindi, se la query non ha l'ordinamento esplicito ed è possibile che alcuni record abbiano un numero di riga diverso ogni volta che esegui la query.

Ad esempio, lo esegui per la prima volta e ottieni risultati come questo:

some_column | rownum
____________|________
     A      |    1
     B      |    2
     C      |    3

quindi lo esegui la seconda volta, poiché non hai l'ordinamento esplicito, dbms (per qualche motivo noto a se stesso) decide di restituire risultati come questo:

some_column | rownum
____________|________
     C      |    1
     A      |    2
     B      |    3

2) il punto 1 implica anche che se filtrerai i risultati su rownum genererà una tabella temporanea con TUTTI risultati e poi filtralo

Quindi rownum non è una buona scelta per dividere i risultati. Mentre rimosso sembrava migliore, ha anche dei problemi.

Riga

Se guardi la descrizione ROWID potresti notare che "il valore rowid identifica in modo univoco una riga nel database ".

A causa di ciò e del fatto che quando si elimina una riga si ha un "buco" nella sequenza rowid, i rowid potrebbero essere distribuiti non equamente tra i record della tabella.

Quindi, ad esempio, se hai tre thread e ciascuno recupera 1'000'000 rowid, è possibile che uno ottenga 1'000'000 record e altri due 1 record ciascuno. Quindi uno sarà sopraffatto, mentre altri due moriranno di fame .

Potrebbe non essere un grosso problema nel tuo caso, anche se potrebbe benissimo essere il problema che stai affrontando attualmente con il pattern di chiave primaria.

Oppure se prima prendi tutti i rowid nel dispatcher e poi li dividi equamente (come suggerito da peter.petrov) che potrebbero fare la cosa, anche se recuperare 80 milioni di ID suona ancora come molti, penso che sarebbe meglio dividere con uno sql-query che restituisce i bordi dei blocchi.

Oppure potresti risolvere il problema fornendo una quantità ridotta di rowid per attività e utilizzando il framework Fork-Join introdotto in Java 7, tuttavia dovrebbe essere utilizzato con attenzione .

Un altro punto ovvio:sia rownum che rowid non sono portabili tra i database.

Quindi è molto meglio avere la tua colonna "sharding", ma poi dovrai assicurarti che divida i record in blocchi più o meno uguali.

Tieni inoltre presente che se hai intenzione di farlo in più thread è importante controllare cosa utilizza il database in modalità di blocco , forse blocca semplicemente la tabella per ogni accesso, quindi il multithreading è inutile.

Come altri hanno suggerito, è meglio prima trovare qual è il motivo principale delle basse prestazioni (rete, disco, blocco del database, carenza di thread o forse hai solo query non ottimali:controlla i piani di query).