Voordat mijn vragen worden beantwoord, zou ik het als volgt aanpakken:
Minimaliseer het aantal verklaringen en het werk dat ze doen in relatieve termen.
Alle scenario's gaan ervan uit dat je een tabel met ID's hebt (PURGE_IDS
) om te verwijderen uit TABLE_1
, TABLE_2
, enz.
Overweeg het gebruik van CREATE TABLE AS SELECT voor echt grote verwijderingen
Als er geen gelijktijdige activiteit is en u 30+% van de rijen in een of meer van de tabellen verwijdert, verwijder dan niet; voer een create table as select
met de rijen die u wilt behouden, en verwissel de nieuwe tafel voor de oude tafel. INSERT /*+ APPEND */ ... NOLOGGING
is verrassend goedkoop als je het kunt betalen. Zelfs als je wel wat gelijktijdige activiteit hebt, kun je mogelijk online tafelherdefinitie gebruiken om de tafel ter plekke opnieuw op te bouwen.
Voer geen DELETE-instructies uit waarvan u weet dat deze geen rijen zullen verwijderen
Als er een ID-waarde bestaat in maximaal een van de zes tabellen, houd dan bij welke ID's u hebt verwijderd - en probeer die ID's niet uit een van de andere tabellen te verwijderen.
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;
en herhaal.
Concurrency beheren als dat moet
Een andere manier is om PL/SQL-looping over de tabellen te gebruiken, waarbij een rowcount-limited delete-statement wordt uitgegeven. Dit is hoogstwaarschijnlijk geschikt als er een aanzienlijke gelijktijdige belasting van invoegen/bijwerken/verwijderen is voor de tabellen waartegen u de verwijderingen uitvoert.
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;