Innan mina frågor besvaras så här skulle jag gå tillväga:
Minimera antalet utlåtanden och det arbete de utför i relativa termer.
Alla scenarier förutsätter att du har en tabell med ID:n (PURGE_IDS
) för att radera från TABLE_1
, TABLE_2
, etc.
Överväg att använda CREATE TABLE AS SELECT för riktigt stora raderingar
Om det inte finns någon samtidig aktivitet och du tar bort 30+ % av raderna i en eller flera av tabellerna, ta inte bort; utför en create table as select
med de rader du vill behålla och byt ut det nya bordet mot det gamla. INSERT /*+ APPEND */ ... NOLOGGING
är förvånansvärt billigt om du har råd. Även om du har viss samtidig aktivitet, kanske du kan använda Online Table Redefinition för att bygga om tabellen på plats.
Kör inte DELETE-satser som du vet inte kommer att radera några rader
Om ett ID-värde finns i högst en av de sex tabellerna, håll sedan reda på vilka ID:n du har tagit bort - och försök inte ta bort dessa ID:n från någon av de andra tabellerna.
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;
och upprepa.
Hantera samtidighet om du måste
Ett annat sätt är att använda PL/SQL-looping över tabellerna och utfärda en radbegränsad delete-sats. Detta är med största sannolikhet lämpligt om det finns en betydande insättning/uppdatering/borttagning av samtidig belastning mot tabellerna du kör borttagningarna mot.
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;