Der wahlfreie Zugriff auf Daten mit Listenstruktur ist nicht zulässig. Es ist ein Versprechen mit meinem Bruder!
Vor einigen Jahren wurde ich kontaktiert, um einem Java-System zu helfen, das mit Unterstützung einer anderen Abteilung erstellt wurde, da es unglaublich langsam wäre, wenn ich ein wenig Big Data hineinstecken würde.
Nun, wenn Sie sich die Abfrage oder den Index für einen Moment ansehen, wird dies behoben ... Ich ging zur Unterstützung, während ich meine Nase pflückte.
Die Verarbeitung des langsamen Teils war wie folgt.
nur das? Ja das ist es. Parallelverarbeitung ist natürlich keine hochklassige Sache.
Untersuchen Sie, was der Server tut. Die Infrastruktur ist diesmal eine typische 3-Layer-3-Server-Konfiguration.
Alles auf dem WEB-Server kann es sich leisten. Der AP-Server hat eine CPU verbraucht. Da es sich um einen 14-Core-Server (EC2 c4.4xlarge) handelt, ist es traurig, dass die Nutzungsrate 7% beträgt, egal wie hart eine CPU arbeitet. Auf dem DB-Server ist eine gewisse Festplattenlast vorhanden, die Leistung ist jedoch begrenzt.
Ich habe auch das Netzwerk, den Speicher usw. untersucht, aber alle Ressourcen sind überschüssig. Verschiedene Einstellwerte sind ebenfalls normal.
Wie Sie sehen können, wird nur INSERT ausgeführt. Obwohl ich mir Sorgen um die CPU-Auslastung des AP machte, waren alle vor Ort misstrauisch gegenüber der Datenbank und spielten damit herum. Haben Sie am Ende den Fehler von OR Mapper behoben? Ich hatte auch eine nostalgische Erfahrung mit der direkten Verwendung von JDBC.
Es gab jedoch kein Ergebnis und Rambos verärgerte Urlaubsarbeit wurde entschieden ...
Kehren Sie zu den Grundlagen zurück und wiederholen Sie die Analyse der Logikverarbeitungszeit. Unter dem Zeugnis, dass "ich das Gefühl habe, dass die Verarbeitung mit fortschreitender Anzahl von Schleifen schwerer wird" Ich beschloss, die Beziehung zwischen der Anzahl der Schleifen und der Verarbeitungszeit einer Schleife herauszufinden.
Das Folgende ist ein Bild der Analyseergebnisse. Wir haben die Menge der Eingabedaten geändert und N10.000 und 20.000 verglichen.
** "Die Hälfte danach ... !!" **
Die kleineren Daten sind die erste Hälfte der größeren Daten, sodass sie je nach Inhalt der Daten nicht zu schwanken scheinen.
Bei näherer Betrachtung war die Linie am oberen Rand des Diagramms die Zeit, die am meisten Zeit in Anspruch nahm:
Der Typ der Variablen data
ist List <MyClass>
.
MyClass record = data.get(i);
Ich war erstaunt darüber. Nur die Elemente aus der Liste zu bekommen, ist wahnsinnig langsam. Jemand öffnete den Mund.
** "Dies ist eine verknüpfte Liste, nicht wahr?" **
Das Abrufen des 10.000sten N der verknüpften Liste mit 2N Millionen Datensätzen hat enorm viel Zeit in Anspruch genommen. Basierend auf der halben Größe der Liste wird möglicherweise von unten auf die Daten in der zweiten Hälfte zugegriffen.
Die Probleme, die uns zu einer Pause einluden, endeten mit einer Änderung der Refactoring-Ebene, bei der die for-Anweisung in eine erweiterte for-Anweisung geändert wurde.
for (int i = 0; i < data.size(); i++) {
MyClass record = data.get(i);
...
}
↓
int i = 0;
for (MyClass record: data) {
...
i++;
}
Was ist der Unterschied auf den ersten Blick? Obwohl es sich um eine Änderung handelt, wird für List vor der Änderung ein Direktzugriff ausgeführt. Nach der Änderung wurde es zu einem sequentiellen Zugriff (von Iterator), und wenn die Anzahl der Daten groß war, gab es einen großen Leistungsunterschied.
Der Grund, warum ich die erweiterte for-Anweisung zuerst nicht verwendet habe, war, dass ich den Wert von i in diesem Prozess verwenden wollte. Ich wünschte, Java hätte eine Python-Aufzählung ... (Groll)
Recommended Posts