私の質問に答える前に、これが私がそれについて行く方法です:
ステートメントの数とそれらが発行する作業を相対的な観点から最小限に抑えます。
すべてのシナリオは、IDのテーブル(PURGE_IDS
があることを前提としています )TABLE_1
から削除します 、TABLE_2
、など。
非常に大きな削除にはCREATETABLEASSELECTの使用を検討してください
同時アクティビティがなく、1つ以上のテーブルの行の30%以上を削除する場合は、削除しないでください。 create table as select
を実行します 保持したい行を使用して、新しいテーブルを古いテーブルと交換します。 INSERT /*+ APPEND */ ... NOLOGGING
あなたがそれを買う余裕があれば驚くほど安いです。同時アクティビティがある場合でも、オンラインテーブル再定義を使用してテーブルをインプレースで再構築できる場合があります。
行が削除されないことがわかっているDELETEステートメントを実行しないでください
6つのテーブルのうち最大で1つにID値が存在する場合は、削除したIDを追跡し、他のテーブルからそれらのIDを削除しようとしないでください。
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;
繰り返します。
必要に応じて同時実行性を管理する
もう1つの方法は、PL / SQLを使用してテーブルをループし、行数が制限された削除文を発行することです。これは、削除を実行しているテーブルに対して、挿入/更新/削除の同時負荷が大きい場合に最も適切である可能性があります。
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;