我们有一个巨大的数据库清理行动即将到来,将有大约1亿行删除总数。有40个表删除数据。这里是我的想法,我愿意接受建议
1方法
大容量收集,然后删除,同时记录删除的行。每100行提交一次
示例->
--define record and needed variables
commit_counter NUMBER := 0;
COMMIT_LIMIT CONSTANT NUMBER := 100;
v_total_deleted_services NUMBER := 0;
TYPE t_record_entity_test IS RECORD (
ENTITY_ID NUMBER,
SOURCE VARCHAR2(100),
SOURCE_ID VARCHAR2(100),
MESSAGE_ID VARCHAR2(100),
STATUS VARCHAR2(200)
);
TYPE t_record_entity_tests IS TABLE OF t_record_entity_test INDEX BY PLS_INTEGER;
v_records_test t_record_entity_tests;
个字符
2方法
批量收集并记录哪些行被删除。一次删除所有行,然后在最后提交。不知道是否可以,因为其中一个操作可能会删除1000万行
--define record and needed variables
v_total_deleted_services NUMBER := 0;
TYPE t_record_entity_test IS RECORD (
ENTITY_ID NUMBER,
SOURCE VARCHAR2(100),
SOURCE_ID VARCHAR2(100),
MESSAGE_ID VARCHAR2(100),
STATUS VARCHAR2(200)
);
TYPE t_record_entity_tests IS TABLE OF t_record_entity_test INDEX BY PLS_INTEGER;
v_records_test t_record_entity_tests;
//Make cursor
CURSOR c_services IS
SELECT --all the data needed--
OPEN c_services;
LOOP
FETCH c_services BULK COLLECT INTO v_records_test LIMIT 10000;
EXIT WHEN v_records_test.COUNT = 0;
FORALL i IN 1..v_records_test.COUNT
INSERT INTO DELETE_LOG_TEST(SOURCE, SOURCE_ID, status, log_date)
VALUES (v_records_test(i).SOURCE, v_records_test(i).SOURCE_ID, 'Service DELETED,' || ' Status: ' ||v_records_test(i).status , SYSDATE);
end loop;
close c_services;
DELETE FROM SERVICE WHERE ENTITY_ID = --select entity_id of data needed to be deleted that is the same data that's in the cursor;
v_total_deleted_services := v_total_deleted_services + SQL%ROWCOUNT;
commit;
--log number of deleted rows
的字符串
什么是更好的方法,是否有第三种方法比这两种方法更好?
2条答案
按热度按时间qij5mzcb1#
如果您可以在应用程序停机时执行此操作,并且您正在删除一个大表的重要部分,那么使用您想要保留的行创建一个新段比删除您不想要保留的行更有效。最有效的是CTAS和替换:
字符串
缺点是你还必须编写脚本并重新应用任何从属对象,如索引,约束,触发器和赠款。但这是完成任务的最有效方法(最少的处理时间)。
另一种方法效率稍低,但在处理从属对象时不太需要注意,它使用相同的概念,但移动数据两次,因此原始对象仍然是永久对象:
型
这里的缺点是表会暂时空着,所以你的应用最好关闭。这两种技术都会导致一个表不再包含你想要删除的行,而另一个表包含原始内容,以防你需要恢复。然后,你可以计划在确定不需要数据后删除
abc$old
表,这样你就可以释放空间。当然,如果你必须在应用程序使用这些表的同时在线执行这些维护操作,那么这种需求将迫使你使用某种渐进的批量删除过程,比如你正在考虑的那种。这将慢得多,但侵入性较小。
efzxgjgh2#
你没有处理任何异常。你确定所有行的
delete
操作都正常吗?例如,外键约束呢?总之:如果你一行一行地做,它是慢慢地,它肯定会花时间删除1000万行(如你所说)。如果你切换到设置处理,它可以更快-而不是
forall
-使用table
函数。类似于这样的:日志表:
字符串
示例表;应该删除
deptno <> 30
的行:型
程序:
型
测试结果:
型
日志:
型
至于提交(我没有在这里实现;你知道怎么做):100(在我看来)太低了;设置它为10000(等于你在
fetch
中使用的限制)。提醒您:考虑异常处理(如有必要)。