Avant de répondre à mes questions, voici comment je procéderais :
Minimisez le nombre de déclarations et le travail qu'elles font émis en termes relatifs.
Tous les scénarios supposent que vous disposez d'une table d'ID (PURGE_IDS
) à supprimer de TABLE_1
, TABLE_2
, etc.
Envisagez d'utiliser CREATE TABLE AS SELECT pour les suppressions très importantes
S'il n'y a pas d'activité simultanée et que vous supprimez plus de 30 % des lignes dans une ou plusieurs tables, ne les supprimez pas ; effectuer un create table as select
avec les lignes que vous souhaitez conserver et remplacez la nouvelle table par l'ancienne table. INSERT /*+ APPEND */ ... NOLOGGING
est étonnamment bon marché si vous pouvez vous le permettre. Même si vous avez une activité simultanée, vous pourrez peut-être utiliser la redéfinition de table en ligne pour reconstruire la table sur place.
N'exécutez pas d'instructions DELETE dont vous savez qu'elles ne supprimeront aucune ligne
Si une valeur d'ID existe dans au plus l'une des six tables, gardez une trace des ID que vous avez supprimés - et n'essayez pas de supprimer ces ID des autres tables.
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;
et répétez.
Gérez la simultanéité si nécessaire
Une autre méthode consiste à utiliser une boucle PL/SQL sur les tables, en émettant une instruction de suppression limitée au nombre de lignes. Ceci est probablement approprié s'il existe une charge simultanée importante d'insertion/mise à jour/suppression sur les tables sur lesquelles vous exécutez les suppressions.
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;