Ich habe eine Tabelle mit 500 Millionen Zeilen (und wächst)
Ich habe Folgendes getan, um die Leistung von Einsätzen zu verbessern:
Auf der Datenbankseite:
- Alle Indizes und Einschränkungen wurden gelöscht
- Protokollierung deaktiviert
Auf der Anwendungsseite:
- Von JPA-verwalteten Entitäten zu nativen Einfügeabfragen gewechselt und der Abfrage einen Oracle-Hinweis hinzugefügt
- Es wurde versucht, in Stapeln pro 1k / 2k / 3k Zeilen festzuschreiben
- Es wurde versucht, parallel (mehrere Threads, Threadanzahl = Kernanzahl auf dem Server) in eine Tabelle zu schreiben
Dies gab mir ungefähr 300 Zeilen pro Sekunde
Zusätzlich versucht:
- Schreiben Sie parallel in Stapeln in mehrere Tabellen (um die Ergebnisse mit UNION zu gruppieren und dann zurückzusetzen).
Dies gab mir ungefähr 1k Zeilen pro Sekunde, aber auf leeren Tabellen. Aber als ich Tabellen mit Dummy-Daten (jeweils 200 Millionen) füllte, sank die Geschwindigkeit der Einfügungen auf 250 - 300 pro Sekunde.
Könnte jemand vorschlagen, was ich sonst noch tun kann, um Einsätze zu beschleunigen? Grundsätzlich möchte ich zuerst verstehen, was der Engpass ist (was sein könnte).
UPD: Die Tabelle ist nach Einfügedatum unterteilt. Die Tabelle enthält ca. 60 Spalten. Die meisten Spalten sind VARCHAR2 (2000 BYTE).
/*+APPEND*/
Hinweis wird bei einzeiligen Einfügungen ignoriert (wenn Sie sich nicht umINSERT INTO ... SELECT
das Anhängen gekümmert haben). (3) Sie sollten ein SQL * Loader-Beispiel mitdirect=true
einrichten, um eine Basislinie zu erstellen, wie von @parsifal vorgeschlagen.Antworten:
Ich habe gerade die aktualisierte 60-Spalten-Tabelle mit hauptsächlich VARCHAR (2k) -Feldern gesehen - das ist (möglicherweise) eine Monstertabelle.
Das Wichtigste zuerst ...
Sie müssen zuerst Ihren Engpass verstehen. Gehen Sie auf der App-Seite ganz zurück zu Ihrer Single-Threaded-Batch-Insert-Lösung (jeweils 1/2 / 3k) und starten Sie sie, melden Sie sich beim DB-Computer an und führen Sie ein "Top" aus - sehen Sie, wie viel Zeit, die der DB-Prozess benötigt UND wie viel (falls vorhanden) wa% Zeit die Maschine anzeigt.
Wenn oben JEDE Zeit angezeigt wird, bedeutet dies, dass Ihre Datenbank an E / A gebunden ist und Sie wahrscheinlich mehrere DB-Computer (Shards) in Betracht ziehen oder SSDs auf den Host-Computer werfen müssen.
Das ist es; Ihre Forschung hört hier auf. Es spielt keine Rolle, wie viel CPU die Datenbank beansprucht oder wie gesättigt Ihr App-Client war. Wenn Sie Probleme mit der E / A-Latenz auf der Host-Datenbank haben, ist dies so schnell wie nie zuvor.
TIPP Wenn Hardwareänderungen nicht in Frage kommen, können Sie je nach ausgeführtem Dateisystem (Linux) versuchen, die Protokollierung oder das Schreiben von Metadaten für die Datenbank zu deaktivieren, um die Leistung auf Dateisystemebene geringfügig zu verbessern. Sie können unter NTFS etwas Ähnliches tun, aber dies gibt Ihnen nur einen kleinen Schub. Dies wird nicht 2x sein.
Nun, zweite Dinge an zweiter Stelle ...
Angenommen, Sie hatten so gut wie keine Wartezeit, aber Ihre CPU ist vollständig vom DB-Prozess abhängig. Sie können jetzt nur noch mehr DB-Maschinen (Shards) einführen und die Arbeit aufteilen.
Auch hier sind Sie mit Ihrer Recherche fertig, wenn dies der Fall ist. Sie können nichts tun, um die CPU schneller zu machen.
Zuletzt dritte Dinge ... dritte ...
Nehmen wir an, die DB macht nicht viel. Wechseln Sie dann zu dem Clientcomputer, auf dem die Batch-Einfügung ausgeführt wird, und überprüfen Sie die CPU-Auslastung. Wenn ja, starten Sie weitere Maschinen, die genau die gleichen Batch-Einsätze ausführen, und prüfen Sie, ob Sie eine lineare Rampe erhalten können.
Wenn die CPU nicht gebunden ist, starten Sie weitere Threads auf demselben Computer, bis sie gebunden ist, und sehen Sie, wie die DB skaliert.
Ich denke, Sie haben das vielleicht bereits versucht. Ich vermute also, dass entweder Ihr Client-Host bereits fixiert war (und mehr Threads keinen Unterschied machen werden) oder dass die Datenbank bereits an ihre Grenzen gestoßen ist und nicht weiter skalieren kann.
Nachtrag
Das Ausführen von Raw-Einfügungen für eine nicht indizierte Tabelle, die keinen Müll enthält, ist im Wesentlichen eine APPEND-Operation, die so schnell ausgeführt werden sollte, wie die Festplatte die Schreibvorgänge verarbeiten kann.
Das Erstellen weiterer Tabellen auf demselben Host-Computer hilft nicht weiter, wenn es Ihre Festplattensuche erhöht (um zu den anderen Tabellen auf der Festplatte zu gelangen, an die angehängt werden soll), und verlangsamt die Arbeit.
Es ist wichtig, zuerst diesen Engpass herauszufinden, dann können wir ihn verdammt noch mal optimieren.
Ich hoffe, das hilft! Halten uns auf dem Laufenden.
quelle
Wenn Sie das direkte Einfügen eines Pfads mit dem Hinweis zum Anhängen aufrufen, wird eine exklusive Sperre für die gesamte Tabelle angewendet, sodass das Einfügen mehrerer Threads nicht hilfreich ist. Sie müssten bei jeder Einfügung explizit eine andere Partition ansprechen ...
... um exklusive Sperren auf Partitionsebene zu erhalten. Sie können dies höchstwahrscheinlich nicht mit einer Tabelle tun, die am Einfügedatum partitioniert ist, aber Sie können die zusammengesetzte Partitionierung (keine Unterpartitionierung) verwenden, um mehrere Partitionen pro eindeutigem Bereich von Einfügedaten zu erhalten.
Legen Sie nicht in der Mitte der Einsätze fest, sondern nur am Ende.
quelle