sql >> Databasteknik >  >> RDS >> Oracle

Flertrådsdatabasläsning

Nätverk

Först och främst, sedan jag använde rowid och rownum är leverantörslås ändå, bör du överväga att använda databaslagrade rutiner. Det kan avsevärt minska omkostnaderna för att överföra data från databasen till applikationsservern (särskilt om de är på olika maskiner och anslutna via nätverk).

Med tanke på att du har 80 miljoner poster att överföra kan det vara den bästa prestandaökningen för dig, även om det beror på vilken typ av arbete dina trådar gör.

Uppenbarligen skulle ökad bandbredd också hjälpa till att lösa nätverksproblem.

Diskprestanda

Innan du gör ändringar i koden kontrollera hårddiskbelastningen medan uppgifter körs, kanske den helt enkelt inte kan hantera så mycket I/O (10 trådar som läses samtidigt).

Att migrera till SSD/RAID eller klustringsdatabas kan lösa problemet. Om du ändrar hur du kommer åt databasen kommer det inte att göra det i så fall.

Multithreading kan lösa CPU-problem, men databaser beror mest på disksystem.

Rownum

Det finns ett par problem du kan möta om du ska implementera det med rowid och rownum.

1) rownum genereras i farten för varje frågas resultat. Så om frågan inte har explicit sortering och det är möjligt att en post har olika radnummer varje gång du kör frågan.

Till exempel kör du det första gången och får resultat så här:

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

sedan kör du det andra gången, eftersom du inte har explicit sortering, bestämmer sig dbms (av någon anledning känd för sig själv) för att returnera resultat så här:

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

2) punkt 1 innebär också att om du kommer att filtrera resultat på rownum den kommer att generera en tillfällig tabell med ALLA resultat och filtrera det sedan

rownum är inte ett bra val för att dela upp resultat. Medan rovid verkade bättre, den har också några problem.

Rowid

Om du tittar på ROWID-beskrivningen du kanske märker att "rovid-värde unikt identifierar en rad i databasen ".

På grund av det och det faktum att när du tar bort en rad har du ett "hål" i radsekvensen, kan rader fördelas inte lika mellan tabellposter.

Så om du till exempel har tre trådar och var och en hämtar 1 000 000 rader, är det möjligt att en får 1 000 000 poster och andra två 1 post vardera. Så en kommer att bli överväldigad, medan två andra svälter .

Det kanske inte är en stor sak i ditt fall, även om det mycket väl kan vara det problem du står inför för närvarande med primärnyckelmönstret.

Eller om du först hämtar alla rader i dispatcher och sedan delar dem lika (som peter.petrov föreslog) så skulle det kunna göra saken, även om att hämta 80 miljoner id fortfarande låter mycket, tror jag att det skulle vara bättre att göra uppdelningen med en sql-fråga som returnerar gränser för bitar.

Eller så kan du lösa det problemet genom att ge ett lågt antal rader per uppgift och använda Fork-Join-ramverket som introducerats i Java 7, men det ska vara använd försiktigt .

Också uppenbar poäng:både rownum och rowid är inte portabla över databaser.

Så det är mycket bättre att ha en egen "sharding"-kolumn, men då måste du själv se till att den delar upp rekord i mer eller mindre lika stora bitar.

Tänk också på att om du ska göra det i flera trådar är det viktigt att kontrollera vad låsningslägesdatabas använder , kanske det bara låser tabellen för varje åtkomst, då är multithreading meningslöst.

Som andra föreslog, bör du först hitta vad som är huvudorsaken till låg prestanda (nätverk, disk, databaslåsning, trådsvält eller kanske du bara har suboptimala frågor - kontrollera frågeplanerna).



  1. 'PDOException' Syntaxfel eller åtkomstöverträdelse:1064 Du har ett fel i din SQL-syntax; kontrollera

  2. Oracle Trigger för att uppdatera samma tabell

  3. Bästa sättet att lagra och hämta synonymer i databasen mysql

  4. Skapa Oracle Cursor med Java-program