Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Maneira ideal de DELETE linhas especificadas do Oracle


Antes de minhas perguntas serem respondidas, é assim que eu faria:

Minimize o número de declarações e o trabalho que elas fazem emitidos em termos relativos.

Todos os cenários pressupõem que você tenha uma tabela de IDs (PURGE_IDS ) para excluir de TABLE_1 , TABLE_2 , etc

Considere o uso de CREATE TABLE AS SELECT para exclusões muito grandes

Se não houver atividade simultânea e você estiver excluindo mais de 30% das linhas em uma ou mais tabelas, não exclua; execute um create table as select com as linhas que você deseja manter e troque a nova tabela pela antiga. INSERT /*+ APPEND */ ... NOLOGGING é surpreendentemente barato se você puder pagar. Mesmo se você tiver alguma atividade simultânea, poderá usar a redefinição de tabela online para reconstruir a tabela no local.

Não execute instruções DELETE que você sabe que não excluirão nenhuma linha

Se um valor de ID existir no máximo em uma das seis tabelas, acompanhe quais IDs você excluiu - e não tente excluir esses IDs de nenhuma das outras tabelas.
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 repita.

Gerencie a simultaneidade se for necessário

Outra maneira é usar o loop PL/SQL sobre as tabelas, emitindo uma instrução de exclusão limitada por contagem de linhas. Isso provavelmente é apropriado se houver uma carga simultânea de inserção/atualização/exclusão significativa nas tabelas nas quais você está executando as exclusões.
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;