Oracle
 sql >> Base de données >  >> RDS >> Oracle

Moyen optimal pour SUPPRIMER les lignes spécifiées d'Oracle

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;