Plsql 使用PL/SQL删除大量记录

Plsql 使用PL/SQL删除大量记录,plsql,oracle11g,Plsql,Oracle11g,我想使用PL/SQL删除大量记录。记录由日期字段标识,该字段标识上次修改记录的时间。我不想消耗太多的资源,所以我认为应该限制要删除的记录的数量,在我看来,伪列ROWNUM可以满足这个目的。然后,我检查受更新影响的行数并重复,直到受影响的行数为0 我正在寻找这样做的最佳实践建议。我还担心我收到的警告: “应重构包含DML语句的循环,以使用大容量收集和FORALL。” 但是当我在谷歌上搜索这个主题时,它似乎不适用于我正在尝试做的事情,或者是我正在做的事情 欢迎您的意见和建议 CREATE OR RE

我想使用PL/SQL删除大量记录。记录由日期字段标识,该字段标识上次修改记录的时间。我不想消耗太多的资源,所以我认为应该限制要删除的记录的数量,在我看来,伪列ROWNUM可以满足这个目的。然后,我检查受更新影响的行数并重复,直到受影响的行数为0

我正在寻找这样做的最佳实践建议。我还担心我收到的警告:

“应重构包含DML语句的循环,以使用大容量收集和FORALL。”

但是当我在谷歌上搜索这个主题时,它似乎不适用于我正在尝试做的事情,或者是我正在做的事情

欢迎您的意见和建议

CREATE OR REPLACE PACKAGE BODY MY_PURGE
AS
   PROCEDURE PURGE_MY_TABLE (v_Cut_Off_Date   IN     DATE,
                                 C_MAX_DELETE     IN NUMBER,
                                 DEL_COUNT        OUT NUMBER)
   IS
      v_RECORDS_DELETED   NUMBER := 0;
      V_DONE              BOOLEAN := FALSE;
   BEGIN
      DEL_COUNT := 0;

      WHILE NOT V_DONE
      LOOP
         DELETE FROM MYTABLE
               WHERE     UPDT_TIMESTMP < v_Cut_Off_Date
                     AND ROWNUM <= C_MAX_DELETE;

         v_RECORDS_DELETED := SQL%ROWCOUNT;
         DEL_COUNT := DEL_COUNT + v_RECORDS_DELETED;

         IF (v_RECORDS_DELETED = 0)
         THEN
            V_DONE := TRUE;
         END IF;

         COMMIT;
      END LOOP;
   END;
创建或替换包体MY\u PURGE
作为
程序清除我的表格(v_截止日期),
C_MAX_删除数字,
德鲁计数(数字)
是
v_记录_删除编号:=0;
V_DONE BOOLEAN:=FALSE;
开始
删除计数:=0;
虽然还没做完
环
从MYTABLE中删除
其中UPDT_TIMESTMP和ROWNUM您关心消耗哪些资源?一个
DELETE
语句将是最有效的方法*。假设这是需要定期执行的操作,那么数据库的大小应该根据
UNDO
表空间进行适当调整,以允许您执行单个
DELETE

实际上,退一步说,最有效的方法是按
UPDT\u TIMESTMP
对表进行分区,并删除旧分区。但是分区是企业版许可证之外的额外成本选项,对表进行分区可能会对系统产生其他影响

如果您确实需要使用临时提交批量删除行,那么这似乎是一个非常合理的实现。如果单<代码>删除>代码>语句占用了我每晚处理窗口的一大部分,我只会考虑这一点,我担心<>代码>删除>代码>在几个小时后可能会失败,这会导致整个进程的回滚和重新启动。批量删除比正常情况下执行单个
DELETE
要慢,但重新启动会更容易


在这种特殊情况下,建议使用
批量收集
全部收集
。它将适用于更常见的情况,即有人从一个或多个源表中选择数据,用PL/SQL进行一些处理,然后将数据写入目标表。通过批量操作而不是通过缓慢的逐行处理来实现这一点会更有效。但是,将其作为一个
插入项来执行将更加有效。。。选择

此清除过程每月运行一次,删除约2000万条记录。我担心在一个事务中可能会消耗多少日志空间。@Paul-哪个“日志空间”<代码>撤消
<代码>重做?还有别的吗?2000万行并不是太多,我希望这不会超过一两分钟,除非有更多的事情发生(例如触发器)。频繁提交只会导致数据库生成更多的
REDO
(并花费更多的时间等待
REDO
)。这可能会使您更快地释放
UNDO
空间,但是您的
UNDO
表空间的大小确实应该适合这种循环过程。