【发布时间】:2020-07-24 07:50:51
【问题描述】:
我有一种情况,我需要从我的 Oracle 数据库中删除日志表中的数据。该表包含大约 3159037 行的 CLOB 内容,现在作为维护活动,我需要通过保留当前日期的最后 6 个月来清除旧数据。我设计了 PL/SQL 程序来实现这一点,但是在测试期间我发现即使删除 1000 条记录,该过程也需要大约 22 秒才能完成执行。现在假设我们有超过 100000 条记录要删除,这将花费大量时间来完成它的执行。
谁能提出更好的方法来解决这个问题。
下面是我当前的脚本,它具有 FORALL 和 BULK COLLECT 功能以获得性能优势。
CREATE OR replace PROCEDURE Integration_data_purge
authid current_user
AS
c_limit CONSTANT PLS_INTEGER DEFAULT 100;
CURSOR int_cur IS
SELECT a.ROWID AS a_rowid,
b.ROWID AS b_rowid
FROM integration_log a,
integration_errors b
WHERE a.error_log_id = b.error_rec_id(+)
AND Trunc(a.insert_date) < Trunc(SYSDATE) - 180;
TYPE int_aat
IS TABLE OF int_cur%ROWTYPE INDEX BY PLS_INTEGER;
l_integration_log INT_AAT;
--l_count INTEGER := 1;
start_time NUMBER;
end_time NUMBER;
BEGIN
start_time := dbms_utility.get_time;
OPEN int_cur;
LOOP
FETCH int_cur bulk collect INTO l_integration_log limit c_limit;
--DBMS_OUTPUT.put_line ('Retrieved in RUN '|| l_count ||' = ' ||
-- l_integration_log.COUNT);
EXIT WHEN l_integration_log.count = 0;
--if l_integration_log.count <> 0 then
forall indx IN 1 .. l_integration_log.count
DELETE FROM integration_log
WHERE ROWID = L_integration_log(indx).a_rowid;
--DBMS_OUTPUT.put_line ('Total rows deleted from INTEGRATION_LOG = ' ||
--SQL%ROWCOUNT);
forall indx IN 1 .. l_integration_log.count
DELETE FROM integration_errors
WHERE ROWID = L_integration_log(indx).b_rowid;
--DBMS_OUTPUT.put_line ('Total rows deleted from INTEGRATION_ERRORS = ' ||
--SQL%ROWCOUNT);
--l_count := l_count + 1;
--end if;
--commit;
END LOOP;
CLOSE int_cur;
end_time := dbms_utility.get_time;
dbms_output.Put_line('Execution Completed : '
|| To_char(( end_time - start_time ) / 100)
|| ' Seconds');
END;
【问题讨论】:
-
如果表
integration_errors具有表integration_log的外键,并且您在定义外键时添加了ON DELETE CASCADE,那么从integration_log中删除一行也将删除表中的所有相关行表integration_errors. -
外键减慢所有操作。我不建议将它们用于简单的日志表。此外,“on delete cascade”对父表中的每一行都运行删除,所以它会是缓慢的设计。
标签: oracle