Netwerk
Allereerst sinds het gebruik van rowid en rownum hoe dan ook vendor-lock is, moet u overwegen om in de database opgeslagen routines te gebruiken. Het kan de overhead van het verzenden van gegevens van de database naar de applicatieserver aanzienlijk verminderen (vooral als ze zich op verschillende machines bevinden en via het netwerk zijn verbonden).
Aangezien je 80 miljoen records moet verzenden, zou dat de beste prestatieverbetering voor je kunnen zijn, hoewel het afhangt van het soort werk dat je threads doen.
Het is duidelijk dat het vergroten van de bandbreedte ook zou helpen om netwerkproblemen op te lossen.
Schijfprestaties
Voordat u wijzigingen in de code aanbrengt, controleert u de belasting van de harde schijf terwijl taken worden uitgevoerd, misschien kan het gewoon niet zoveel I/O aan (10 threads tegelijkertijd lezen).
Migreren naar SSD/RAID of clusterdatabase kan het probleem oplossen. Terwijl het veranderen van de manier waarop u toegang krijgt tot de database in dat geval niet.
Multithreading zou CPU-problemen kunnen oplossen, maar databases zijn meestal afhankelijk van het schijfsysteem.
Rownum
Er zijn een aantal problemen waarmee u te maken kunt krijgen als u het gaat implementeren met rowid en rownum.
1) rijnummer wordt direct gegenereerd voor de resultaten van elke zoekopdracht. Dus als de query geen expliciete sortering heeft en het is mogelijk dat sommige records elke keer dat u de query uitvoert een ander rijnummer hebben.
U voert het bijvoorbeeld de eerste keer uit en krijgt de volgende resultaten:
some_column | rownum
____________|________
A | 1
B | 2
C | 3
dan voer je het een tweede keer uit, aangezien je geen expliciete sortering hebt, besluit dbms (om een of andere reden die hij zelf kent) om resultaten als deze te retourneren:
some_column | rownum
____________|________
C | 1
A | 2
B | 3
2) punt 1 houdt ook in dat als u resultaten gaat filteren op rownum het genereert een tijdelijke tabel met ALL resultaten en filter het vervolgens
Dus rownum is geen goede keuze voor het splitsen van resultaten. Terwijl roem leek beter, het heeft ook wat problemen.
Rowid
Als je kijkt naar de ROWID-beschrijving je merkt misschien dat de "rowid-waarde op unieke wijze een rij identificeert in de database ".
Vanwege dat en het feit dat wanneer u een rij verwijdert, u een "gat" heeft in de rowid-volgorde, kunnen rowids niet gelijk worden verdeeld over tabelrecords.
Dus als je bijvoorbeeld drie threads hebt en elk 1.000.000 rowids haalt, is het mogelijk dat de ene 1.000.000 records krijgt en de andere twee 1 record elk. Dus één zal overweldigd zijn, terwijl twee andere verhongeren .
Misschien is dat in jouw geval niet erg, hoewel het heel goed het probleem kan zijn waarmee je momenteel te maken hebt met het primaire sleutelpatroon.
Of als je eerst alle rowids in de dispatcher ophaalt en ze vervolgens gelijk verdeelt (zoals peter.petrov suggereerde), dat zou het ding kunnen doen, hoewel het ophalen van 80 miljoen ID's nog steeds als veel klinkt, denk ik dat het beter zou zijn om de splitsing met één te doen sql-query die randen van chunks retourneert.
Of u kunt dat probleem oplossen door een laag aantal rowids per taak te geven en het Fork-Join-framework te gebruiken dat is geïntroduceerd in Java 7, maar het is zou moeten zijn gebruikt voorzichtig .
Ook voor de hand liggend:zowel rownum als rowid zijn niet overdraagbaar tussen databases.
Het is dus veel beter om uw eigen "sharding"-kolom te hebben, maar dan moet u er zelf voor zorgen dat deze records in min of meer gelijke delen opsplitst.
Houd er ook rekening mee dat als je het in meerdere threads gaat doen, het belangrijk is om te controleren wat de vergrendelmodusdatabase gebruikt , misschien vergrendelt het gewoon de tabel voor elke toegang, dan is multithreading zinloos.
Zoals anderen suggereerden, kun je beter eerst uitzoeken wat de belangrijkste reden is voor de lage prestaties (netwerk, schijf, databasevergrendeling, uithongering van threads of misschien heb je gewoon suboptimale zoekopdrachten - controleer de queryplannen).