Oracle 11g: Leistungsverbesserungen von Inserts

8

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).

treiben
quelle
Sie wissen, dass bei deaktivierter Protokollierung ein Medienfehler zwischen dem Laden und dem Abschluss der ersten nachfolgenden Sicherung die gesamte Tabelle oder Teile davon im Fall einer direkten Pfadeinfügung nicht wiederherstellbar lässt, oder?
David Aldridge
1
(1) Es kann jeweils nur eine Sitzung an einem Tisch ANHÄNGEN. (2) Der /*+APPEND*/Hinweis wird bei einzeiligen Einfügungen ignoriert (wenn Sie sich nicht um INSERT INTO ... SELECTdas Anhängen gekümmert haben). (3) Sie sollten ein SQL * Loader-Beispiel mit direct=trueeinrichten, um eine Basislinie zu erstellen, wie von @parsifal vorgeschlagen.
Vincent Malgrat
Laufen Sie auf realer Hardware oder einer virtuellen Maschine? Wenn es sich um eine VM handelt, sind die Festplattendateien spärlich (dh nicht vollständig vorab zugewiesen)? Bitte bearbeiten Sie Ihre Frage auch mit der Ausgabe eines statspack- oder awr-Berichts (Abschnitt oben wartet).
Philᵀᴹ
Welches Problem / Bedürfnis löst / befriedigt die Partitionierung nach Einfügedatum?
Brian
Woher stammen Ihre Daten für diese Tabelle? Ist dies ein Batch-Laden aus einer ASCII-Datei oder ist es vom Benutzer generiert oder etwas anderes. Bitte erläutern.
RMAN Express

Antworten:

5

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.

Riad Kalla
quelle
2
Warum hast du awr oder statspack nicht erwähnt?
Philᵀᴹ
Mit einem Hinweis zum Anhängen werden alle bis auf einen dieser Threads aufgrund der exklusiven Sperrung inaktiv sein. Ich glaube nicht, dass sich dieser Code in einem Stadium der Effizienz befindet, in dem eine Optimierung auf Systemebene erforderlich ist - es ist die Methodik selbst, die fehlerhaft ist.
David Aldridge
Wenn Sie weiter nachdenken, glaube ich, dass Ihr Ansatz einen grundlegenden Fehler aufweist. Wenn Viktors die Single-Threaded-Batch-Insert-Methode ausprobiert hat und E / A-Wartezeiten hatte, kann dies durch eine ineffiziente Insert-Methode und übermäßiges Festschreiben verursacht werden (Wartezeit bei der Synchronisierung der Protokolldatei). Der wichtigste Schritt sollte sein, die Oracle-Mechanismen zu verstehen und zuerst den am besten geeigneten auszuwählen.
David Aldridge
@DavidAldridge Viktors stellte klar , dass er deaktiviert Protokollierung (und die Indizes) da hatte ich angenommen , es gibt nicht viel anderes der DB war tat neben der eingefügten Daten - Streaming direkt auf die Tabellendatei, weshalb ich ihn nach rechts hatte springen Blick auf Ich / O warte. Vielleicht tut Oracle mehr, das deaktiviert werden sollte / könnte - das ist ein guter Untersuchungspunkt. Ich kenne die Tiefen von Oracle nicht gut genug, um dort leider zu helfen.
Riyad Kalla
4

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 ...

insert /*+ append */ into my_table partition (partition_name_1) ...

... 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.

David Aldridge
quelle
Muss ich den Partitionsnamen in der Abfrage explizit angeben? Ich habe eine Spalte, eine Art Ereignistyp. Ich werde von einer Gruppe von Ereignissen Partition versuchen und machen , so dass jeder Thread Charge von Zeilen einfügt nur von bestimmtem Typ
adrift
Ja, um eine exklusive Sperre auf Tabellenebene zu vermeiden.
David Aldridge
Der APPEND-Hinweis sollte von Oracle für einzeilige Einfügungen ignoriert werden. Die Beschreibung des Prozesses durch das OP scheint einreihige Batch-Einfügungen zu implizieren. Ich bin mir nicht sicher, wie diese behandelt werden. Ich würde keinen ANHANG erraten, aber es müssen einige Tests durchgeführt werden.
Vincent Malgrat
Hmmm, habe das nicht in Betracht gezogen - wenn ja, ist es noch schlimmer.
David Aldridge
Lohnt es sich, mehrzeilige Einfügungen mit APPEND-Hinweis zu versuchen? Wie viele Einträge pro mehrzeiliger Einfügung soll ich dann senden?
treiben