Ich denke, dass Sie dies in JDBC tun können. Ich würde etwas wie das folgende vorschlagen:
- Erstellen Sie zwei oder drei Gewinde. Jeder Thread führt Folgendes durch:
- Erstellen Sie eine Verbindung.
- Erstellen Sie eine vorbereitete Anweisung, die eine disjunkte Untergruppe der Zeilen abruft
- Legen Sie die Abrufgröße auf 100 oder so fest. Auf jeden Fall weniger als 1000.
- Eine Update-Anweisung
- Führen Sie die Abfrage
- Iterate über das Ergebnis gesetzt
- Für jede Zeile Batch fügen Sie die Zeile
- Nach Fetch-Größe Reihen der Batch-
ausführen zu aktualisieren
Nehmen wir an, die Abrufgröße ist 100. Die erste Ausführung wird eine Rundreise machen, die Zeit braucht. Während das passiert, gehen Sie einen anderen Thread. Wenn eine Ausführung die Verarbeitung zurückgibt, führen die nächsten 100 Zeilen keinen Datenbank-Umlauf aus. Die Zeilen wurden bereits abgerufen und die Aktualisierungen werden gebündelt, sodass keine Datenbankumgehung durchgeführt wird. Nach 100 Zeilen führen Sie den Stapel aus, der eine Rundreise durchführt und so die Fäden wechselt. Dann werden 100 weitere Zeilen abgerufen, die die Threads wechseln. Ich bin mir nicht sicher, ob zwei oder drei Threads optimal wären, aber wenn ich raten müsste, würde ich drei ausprobieren.
Aber das oben genannte nimmt an, dass die Maschine nur einen einzelnen Hardware-Thread hat, der nicht wahr ist. Die meisten CPUs unterstützen 12 oder mehr Hardware-Threads, sodass ich tatsächlich 30 oder mehr Threads verwenden würde, je nachdem, was die Hardware unterstützen kann. Selbst mit mehreren CPUs wollen Sie wahrscheinlich nicht mehr als 50 oder mehr Threads, da dies zu Konflikten in der Datenbank führen wird.
Obiges geht davon aus, dass der externe Dienst schnell ist, viel schneller als die Datenbank. Wenn nicht, dann wird jede Zeile auf den externen Dienst warten. In diesem Fall mehr Threads.Da die Aktualisierungen die Datenbank langsamer treffen, ist die Thread-Konkurrenz in der Datenbank weniger bedenklich.
Eine Möglichkeit, die Abfrageergebnisse in disjunkte Teilmengen zu unterteilen ist wie folgt:
SELECT c1, c2, etc, row
FROM (SELECT c1, c2, etc, ROWNUM FROM ...)
WHERE MOD(row, number_of_partitions) = ?
dann die Abfrage param von 0 bis number_of_partitions gesetzt - 1, eine für jeden Thread. Sie müssen dies als Unterabfrage tun, damit ROWNUM richtig funktioniert.
Verwenden Sie keine aktualisierbaren Ergebnissätze. Die Leistung wird miserabel sein, garantiert.
ist die Information benötigt, um die Updates alle in der Datenbank enthalten zu tun? (Formel wird verwendet) oder wenn Sie gesagt haben, dass eine Verarbeitung durchgeführt werden muss, liegt das daran, dass einige der benötigten Informationen für Aktualisierungen lokal sind? – xQbert
Hallo. Nein, die Informationen für das Update sind nicht in der Datenbank enthalten. Ich muss die Datenzeile lesen, dann einen externen Dienst aufrufen, um die berechneten Werte abzurufen, und dann 3 Felder der Zeilen mit den berechneten Werten aktualisieren. – Gilles
@Gilles Wie lange musst du das erreichen? Sie werden Daten in Java ziehen und für jede Zeile einen externen Dienst aufrufen und dann die Datenbank aktualisieren. Lassen Sie uns so tun, als könnten Sie das in 10ms pro Zeile machen, was ich bezweifle, dass Sie dazu in der Lage wären. Es dauert immer noch 9,25 Tage, um den Prozess abzuschließen. Erweitere es von dort. Wenn es 100ms pro Zeile dauert, sind es jetzt 92,5 Tage. Wenn es auf diese Weise geschehen muss, wissen Sie am besten, worauf Sie sich einlassen. – unleashed