Oracle
 sql >> Database >  >> RDS >> Oracle

Modo ottimale per CANCELLARE le righe specificate da Oracle

Prima che le mie domande ricevano risposta, ecco come farei:

Ridurre al minimo il numero di dichiarazioni e il lavoro che svolgono emesse in termini relativi.

Tutti gli scenari presuppongono che tu abbia una tabella di ID (PURGE_IDS ) per eliminare da TABLE_1 , TABLE_2 , ecc.

Considera l'utilizzo di CREATE TABLE AS SELECT per eliminazioni molto grandi

Se non ci sono attività simultanee e stai eliminando oltre il 30% delle righe in una o più tabelle, non eliminare; esegui un create table as select con le righe che desideri mantenere e scambia la nuova tabella con la vecchia tabella. INSERT /*+ APPEND */ ... NOLOGGING è sorprendentemente economico se te lo puoi permettere. Anche se hai qualche attività simultanea, potresti essere in grado di utilizzare la ridefinizione della tabella online per ricostruire la tabella sul posto.

Non eseguire istruzioni DELETE che sai non cancelleranno alcuna riga

Se esiste un valore ID al massimo in una delle sei tabelle, tieni traccia di quali ID hai eliminato e non tentare di eliminare tali ID da nessuna delle altre tabelle.

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;

e ripeti.

Gestisci la concorrenza, se necessario

Un altro modo consiste nell'utilizzare il ciclo PL/SQL sulle tabelle, emettendo un'istruzione di eliminazione limitata al numero di righe. Questo è probabilmente appropriato se c'è un carico simultaneo di inserimento/aggiornamento/eliminazione significativo sulle tabelle su cui stai eseguendo le eliminazioni.

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;