我必须创建一个oracle程序来删除订阅状态被取消且数据超过2个月的客户的所有数据。 总共有 5 亿条记录,大约有 1 亿条需要删除。
我必须创建一个脚本,以便它在每次运行中删除 500 万个,因为一起完成整个操作将花费太长时间。 这就是我所创造的。有没有办法进一步优化?
DECLARE
rows_deleted NUMBER := 0;
max_rows_to_delete NUMBER := 5000000;
retention_date DATE := trunc(sysdate) - INTERVAL '2' MONTH;
BEGIN
DELETE FROM subs
WHERE
EXISTS (
SELECT
1
FROM
Sub_status ss
WHERE
sub.id = ss.id
AND ss.status= 'cancel'
)
AND sub.date <= retention_date
AND ROWNUM <= max_rows_to_delete;
rows_deleted := SQL%rowcount;
-- Log number of rows deleted
dbms_output.put_line('Deleted ' || rows_deleted || ' rows');
COMMIT; -- Commit changes after successful completion
EXCEPTION
WHEN OTHERS THEN
-- Handle exceptions or errors if necessary
ROLLBACK; -- Rollback the transaction if an error occurs
dbms_output.put_line('Error: ' || sqlerrm);
END;
创建一个函数,该函数接受
id
并查找 sub_status
并返回 status
:
CREATE OR REPLACE getsubstatus(in_id integer)
RETURN varchar2 DETERMINISTIC PARALLEL_ENABLE
AS
PRAGMA UDF;
var_status;
BEGIN
SELECT status
INTO var_status
FROM sub_status
WHERE id = in_id;
RETURN var_status;
END;
然后通过查询
all_tab_partitions
获取这些足够旧的分区的分区名称,以便进行归档,并且对于每个分区,使用以下语法移动(重组)分区:
ALTER TABLE subs MOVE PARTITION p202301 INCLUDING ROWS WHERE getsubstatus(id) != 'cancel' PARALLEL(16)
.
Oracle 将在内部创建一个新的分区段,仅由状态不是
cancel
的行组成。如果要删除的目标行是段的重要部分,则插入幸存者比删除快得多。 20%(500m 中的 100m)非常重要。