Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Optimaler Weg, um bestimmte Zeilen aus Oracle zu LÖSCHEN

Bevor meine Fragen beantwortet werden, würde ich folgendermaßen vorgehen:

Minimieren Sie die Anzahl der Erklärungen und die Arbeit, die sie relativ machen.

Alle Szenarien gehen davon aus, dass Sie eine ID-Tabelle haben (PURGE_IDS ) zum Löschen aus TABLE_1 , TABLE_2 usw.

Erwägen Sie die Verwendung von CREATE TABLE AS SELECT für wirklich große Löschungen

Wenn es keine gleichzeitige Aktivität gibt und Sie mehr als 30 % der Zeilen in einer oder mehreren Tabellen löschen, löschen Sie nicht; Führen Sie ein create table as select durch mit den Zeilen, die Sie behalten möchten, und tauschen Sie die neue Tabelle gegen die alte Tabelle aus. INSERT /*+ APPEND */ ... NOLOGGING ist überraschend billig, wenn Sie es sich leisten können. Selbst wenn Sie einige gleichzeitige Aktivitäten haben, können Sie möglicherweise die Online-Tabellenneudefinition verwenden, um die Tabelle direkt neu zu erstellen.

Führen Sie keine DELETE-Anweisungen aus, von denen Sie wissen, dass sie keine Zeilen löschen

Wenn ein ID-Wert in höchstens einer der sechs Tabellen vorhanden ist, verfolgen Sie, welche IDs Sie gelöscht haben – und versuchen Sie nicht, diese IDs aus einer der anderen Tabellen zu löschen.

CREATE TABLE TABLE1_PURGE NOLOGGING
AS 
SELECT ID FROM PURGE_IDS INNER JOIN TABLE_1 ON PURGE_IDS.ID = TABLE_1.ID;

DELETE FROM TABLE1 WHERE ID IN (SELECT ID FROM TABLE1_PURGE);

DELETE FROM PURGE_IDS WHERE ID IN (SELECT ID FROM TABLE1_PURGE);

DROP TABLE TABLE1_PURGE;

und wiederholen.

Verwalten Sie Parallelität, wenn Sie müssen

Eine andere Möglichkeit besteht darin, eine PL/SQL-Schleife über die Tabellen zu verwenden und eine auf die Anzahl der Zeilen beschränkte Löschanweisung auszugeben. Dies ist höchstwahrscheinlich angemessen, wenn es eine erhebliche gleichzeitige Einfüge-/Aktualisierungs-/Löschlast für die Tabellen gibt, für die Sie die Löschvorgänge ausführen.

declare
  l_sql varchar2(4000);
begin
  for i in (select table_name from all_tables 
             where table_name in ('TABLE_1', 'TABLE_2', ...)
             order by table_name);
  loop
    l_sql := 'delete from ' || i.table_name || 
             ' where id in (select id from purge_ids) ' || 
             '   and rownum <= 1000000';
    loop
      commit;
      execute immediate l_sql;
      exit when sql%rowcount <> 1000000;  -- if we delete less than 1,000,000
    end loop;                             -- no more rows need to be deleted!
  end loop;
  commit;
end;