【发布时间】:2018-07-03 10:29:25
【问题描述】:
我希望每 1000 行提交一次,直到所有记录都被删除,我们有超过一百万条记录要删除。
原来:
private static final String DELETE_OLD_REPORTS_FROM_REPORTING =
- "DELETE FROM A_REPORTING\n" +
- "WHERE ID IN(" +
- "SELECT ID FROM A_REPORTING\n" +
- "WHERE STATUS = 'LOADED'\n" +
- "AND CREATE_DT < TO_DATE(:createdDate, 'dd-mon-yyyy'))";
我正在考虑做这样的事情:
"BEGIN\n" +
"LOOP\n" +
"DELETE FROM A_REPORTING\n" +
"WHERE ID IN(" +
"SELECT ID FROM A_REPORTING\n" +
"WHERE STATUS = 'LOADED'\n" +
"AND CREATE_DT < TO_DATE(:createdDate, 'dd-mon-yyyy')\n+" +
"AND ROWNUM <= 10000);\n" +
"EXIT WHEN SQL%rowcount < 9999;\n" +
"COMMIT;\n" +
"END LOOP;\n"+
"COMMIT;\n" +
"END";
但是,有没有更好的方法来做到这一点?这是因为我们收到了 ORA-01555 错误:
ORA-01555:快照太旧:名称为“%segname”的回滚段号 %n 太小。
【问题讨论】:
-
您可以将条件从子查询中提取到
IN并将它们直接添加到外部查询中(从而完全摆脱IN)。也许不相关,但也可能渗入查询。你有STATUS和CREATE_DT的索引吗?这也可能会加快速度。 -
你有 Oralce DB - 对吧?为什么不能在数据库本身中执行删除逻辑?
-
删除一百万行后,表中会有多少行?
-
@sticky bit - 他不能直接在 DELETE 中添加 ROWNUM 过滤器,他添加了子查询来绕过它,并且 STATUS/CREATE_DT 上的过滤必须伴随 ROWNUM。跨度>
-
@GaryMyers:我的意思是第一个没有
ROWNUM的查询。但是IN可以被消除并可能加快查询速度(并且可能足够快以消除对“提交每 n 条记录”杂技的需要)。
标签: sql oracle sql-delete ora-01555