sql >> Base de Datos >  >> RDS >> Oracle

Manera óptima de ELIMINAR filas especificadas de Oracle

Antes de que se respondan mis preguntas, así es como lo haría:

Minimizar el número de sentencias y el trabajo que realizan emitido en términos relativos.

Todos los escenarios asumen que tiene una tabla de ID (PURGE_IDS ) para eliminar de TABLE_1 , TABLE_2 , etc.

Considere usar CREATE TABLE AS SELECT para eliminaciones realmente grandes

Si no hay actividad concurrente y está eliminando más del 30 % de las filas en una o más de las tablas, no elimine; realizar una create table as select con las filas que desea conservar y cambie la nueva tabla por la antigua. INSERT /*+ APPEND */ ... NOLOGGING es sorprendentemente barato si te lo puedes permitir. Incluso si tiene alguna actividad simultánea, puede usar la redefinición de tablas en línea para reconstruir la tabla en el lugar.

No ejecute instrucciones DELETE que sepa que no eliminarán ninguna fila

Si existe un valor de ID en una de las seis tablas como máximo, realice un seguimiento de los ID que ha eliminado y no intente eliminar esos ID de ninguna de las otras tablas.

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;

y repite.

Gestionar la simultaneidad si es necesario

Otra forma es usar PL/SQL en bucle sobre las tablas, emitiendo una declaración de eliminación limitada en el número de filas. Es muy probable que esto sea apropiado si hay una carga simultánea significativa de inserción/actualización/eliminación en las tablas en las que está ejecutando las eliminaciones.

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;