Преди да получа отговор на въпросите ми, бих постъпил по следния начин:
Намалете до минимум броя на изявленията и работата, която вършат, издадени в относително изражение.
Всички сценарии предполагат, че имате таблица с идентификатори (PURGE_IDS
), за да изтриете от TABLE_1
, TABLE_2
и др.
Помислете за използването на CREATE TABLE AS SELECT за наистина големи изтривания
Ако няма едновременна дейност и изтривате 30+ % от редовете в една или повече от таблиците, не изтривайте; изпълнете create table as select
с редовете, които искате да запазите, и сменете новата таблица със старата. INSERT /*+ APPEND */ ... NOLOGGING
е изненадващо евтино, ако можете да си го позволите. Дори ако имате някаква паралелна дейност, може да сте в състояние да използвате онлайн предефиниране на таблица, за да възстановите таблицата на място.
Не изпълнявайте изрази DELETE, за които знаете, че няма да изтрият редове
Ако идентификационна стойност съществува в най-много една от шестте таблици, следете кои идентификатори сте изтрили – и не се опитвайте да изтриете тези идентификатори от която и да е от другите таблици.
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;
и повторете.
Управлявайте паралелността, ако трябва
Друг начин е да се използва 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;