2 Stimmen

Löschen dauert plötzlich sehr lange

Wir haben ein Futtermittelverfahren, das jeden Tag des Jahres läuft. Dabei löschen wir jeden Tag jede Zeile aus einer Tabelle (ca. 1 Million Zeilen), füllen sie mithilfe von 5 verschiedenen gespeicherten Prozeduren neu auf und übertragen die Transaktion dann. Dies ist die einzige Commit-Anweisung, die wir aufrufen. Plötzlich hat das Löschen begonnen, etwa 2 Stunden in Anspruch zu nehmen. Der Löschvorgang ist auch sehr einfach (delete from T_PROFILE_WORK) Das hat im letzten Jahr perfekt funktioniert, aber in der letzten Woche habe ich dieses Problem bemerkt.

Jede Hilfe in dieser Sache ist sehr willkommen

5voto

Vincent Malgrat Punkte 65127

Überprüfen Sie bitte die Antworten auf diese SO-Frage: "Oracle-Löschabfrage nimmt zu viel Zeit in Anspruch" :

  1. Sie könnten durch eine andere Sitzung blockiert sein (höchstwahrscheinlich). Bevor Sie löschen, sollten Sie sicherstellen, dass niemand sonst die Zeilen sperrt, z.B.: issue SELECT NULL FROM tablename WHERE colname=:value FOR UPDATE NOWAIT,
  2. Es könnte einen ON DELETE TRIGGER geben, der zusätzliche Arbeit leistet,
  3. Prüfung auf UNINDEXED REFERENCE CONSTRAINTS, die auf diese Tabelle zeigen (es gibt eine Skript von AskTom das Ihnen helfen wird, festzustellen, ob solche unindizierte Fremdschlüssel existieren).

Ich würde zuerst die Nummern 2 und 3 überprüfen, denn sie sind am einfachsten zu diagnostizieren.

1 Stimmen

+1 Als Ergänzung zu Vincents ausgezeichneter Antwort und um Tom Kyte zu paraphrasieren: "Was hat sich geändert?" Wenn die Löschanweisung funktioniert hat und jetzt nicht mehr, was hat sich geändert, um dies zu verursachen?

2voto

Rene Punkte 10199

Wenn Sie nur alles aus der Tabelle entfernen wollen, verwenden Sie truncate anstelle von delete.

0 Stimmen

Ich fürchte, das können wir nicht tun. Während diese Tabelle geladen wird, wird unser System weiterhin genutzt. Wenn wir diese Tabelle abschneiden würden, wäre die Anwendung leer, bis diese Tabelle geladen und die Übertragung abgeschlossen ist. (Ich weiß, das ist keine großartige Architektur, aber ich bin dem Projekt beigetreten, nachdem diese Lösung implementiert wurde)

0voto

Gary Myers Punkte 34373

Wie wäre es, wenn Sie eine zweite (vielleicht globale temporäre) Tabelle haben, die Sie aus den gespeicherten Prozeduren befüllen und am Ende einen MERGE in die bestehende Tabelle durchführen. Ohne die Details der Aktivität, Tabellenstrukturen usw. zu kennen, ist es schwer, sicher zu sein. Aber vielleicht geht es schneller.

Wenn Sie die Enterprise Edition mit der Partitionierungsoption haben, können Sie alternativ auch Partition Exchange verwenden.

0voto

Alain Pannetier Punkte 9008

Für das Protokoll, hier ist das Skript von Tom Kyte und von Vincent Malgrat in der akzeptierten Antwort erwähnt (so dass Sie nicht durch die Unmengen von Kommentaren durchsuchen und mehr Links folgen müssen).

Das Skript ergibt todo die Spalten für alle Tabellen; Sie müssen noch herausfinden, welche davon für die Tabelle gelten, in der Sie Zeilen löschen wollen, und welche FK-Tabellen die größte Kardinalität haben.

Anders ausgedrückt: Natürlich brauchen nicht alle Treffer einen Index.

    SELECT table_name,
       constraint_name,
          cname1
       || NVL2 (cname2, ',' || cname2, NULL)
       || NVL2 (cname3, ',' || cname3, NULL)
       || NVL2 (cname4, ',' || cname4, NULL)
       || NVL2 (cname5, ',' || cname5, NULL)
       || NVL2 (cname6, ',' || cname6, NULL)
       || NVL2 (cname7, ',' || cname7, NULL)
       || NVL2 (cname8, ',' || cname8, NULL)
          columns
  FROM (  SELECT b.table_name,
                 b.constraint_name,
                 MAX (DECODE (position, 1, column_name, NULL)) cname1,
                 MAX (DECODE (position, 2, column_name, NULL)) cname2,
                 MAX (DECODE (position, 3, column_name, NULL)) cname3,
                 MAX (DECODE (position, 4, column_name, NULL)) cname4,
                 MAX (DECODE (position, 5, column_name, NULL)) cname5,
                 MAX (DECODE (position, 6, column_name, NULL)) cname6,
                 MAX (DECODE (position, 7, column_name, NULL)) cname7,
                 MAX (DECODE (position, 8, column_name, NULL)) cname8,
                 COUNT (*) col_cnt
            FROM (SELECT SUBSTR (table_name, 1, 30) table_name,
                         SUBSTR (constraint_name, 1, 30) constraint_name,
                         SUBSTR (column_name, 1, 30) column_name,
                         position
                    FROM user_cons_columns) a, user_constraints b
           WHERE a.constraint_name = b.constraint_name
                 AND b.constraint_type = 'R'
        GROUP BY b.table_name, b.constraint_name) cons
 WHERE col_cnt >
          ALL (  SELECT COUNT (*)
                   FROM user_ind_columns i
                  WHERE i.table_name = cons.table_name
                        AND i.column_name IN
                               (cname1,
                                cname2,
                                cname3,
                                cname4,
                                cname5,
                                cname6,
                                cname7,
                                cname8)
                        AND i.column_position <= cons.col_cnt
               GROUP BY i.index_name);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X