2017-12-20 4 views
2

Ich muss Tabelle aktualisieren, die rund 93 Millionen Datensätze hat, am Anfang DB aktualisiert 10 k Datensätze pro 5 Sekunden, jetzt nach rund 60 Millionen aktualisierte Datensätze, nächste 10k Datensätze aktualisieren nimm 30-60 s, weiß nicht, warum ich Spalten aktualisieren muss, die null sind.
I-Schleife mit Commit jeweils 10 k Datensätze:Beschleunigen Sie Updates auf Oracle DB, die viele Datensätze

LOOP 
    UPDATE TABLE 
    SET DATE_COLUMN = v_hist_date 
    WHERE DATE_COLUMN IS NULL 
      AND ROWNUM <= c_commit_limit 
      AND NOT_REMOVED IS NULL; 

    EXIT WHEN SQL%ROWCOUNT = 0; 
    COMMIT; 
    END LOOP; 

Sie irgendwelche Ideen, warum es so viel verlangsamen und wie ist möglich, dieses Update zu beschleunigen?

+0

Ja, es ist Teil des PL/SQL-Codes – Krystian

+0

Warum? Ich habe Spalte mit Null-Werten, wenn es alle aktualisiert, dann wird es beendet, wenn Update 0 Zeilen zurückgeben, hat es mich auf kleineren Tabellen mit z. 1-2 mln Datensätze und es dauerte viel weniger Zeit, aber es gab auch neuere db-Version – Krystian

Antwort

5

Updates sind auch Abfragen. Sie haben keinen EXPLAIN-Plan gepostet, aber wenn Sie nach Spalten filtern, die null sind, scheint es wahrscheinlich, dass Ihre Anweisung einen vollständigen Tabellen-Scan ausführt. Das passt sicherlich zu dem Verhalten, das Sie beschreiben.

Was passiert ist das. Die erste Schleife der FTS findet 10000 Zeilen, die fast sofort zu den WHERE-Kriterien passen. Dann verlassen Sie die Schleife und beginnen erneut. Diesmal liest der FTS dieselben Blöcke erneut, einschließlich der in der vorherigen Iteration aktualisierten Blöcke, bevor er die nächsten 10000 Zeilen findet, die er aktualisieren kann. Und so weiter. Jede Schleife dauert länger, weil der vollständige Tabellenscan für jede Schleife mehr von der Tabelle lesen muss.

Dies ist eine der Strafen für die zufällige Festlegung in einer Schleife. Es ist vielleicht zu spät für Sie, aber ein besserer Ansatz wäre, eine indizierte Spalte wie einen Primärschlüssel zu verfolgen. Wenn Sie einen solchen Tracking-Schlüssel verwenden, können Sie mit einem Index-Scan die Zeilen überspringen, die Sie bereits besucht haben.

+1

Der beste Ansatz wäre, ein einzelnes Update statt der Batch-Updates, die gerade durchgeführt wird, zu tun, um sicherzustellen, dass der UNDO-Tablespace entsprechend bemessen ist. – Boneist

+1

@boneist - Ich stimme dir zwar zu, aber ich denke, es ist schwer, in solchen Situationen ohne weitere Details "das Beste" zu definieren. Das Problem bei der Aktualisierung eines großen Blocks von 93 Millionen Zeilen in einer Anweisung ist das Risiko, dass es umfällt; Wenn das passiert, verlieren wir die ganze Arbeit und müssen es noch einmal tun. Auf der positiven Seite gewinnen wir transaktionale Integrität. Es gibt andere Optionen - wie zum Beispiel das Setzen eines DEFAULT-Werts, die möglicherweise angemessen sind -, wiederum abhängig von dem (nicht spezifizierten) Ziel. – APC

+1

Yup, Sie sind natürlich absolut richtig! – Boneist

Verwandte Themen