在Oracle中,我应该多久提交一次?

4

我正在从一个大的Oracle数据库中删除大量数据。 我遵循的过程是,我首先删除与表B有关联的表A记录,这会导致表B上的级联删除,而表B又会对其他一些表进行级联删除。 所以基本上有几个表彼此相关,并具有级联删除。

目前,此过程在对表A中的若干记录进行迭代时工作,并且我仅在迭代结束时(即所有数据都已删除时)进行COMMIT。该过程需要约30小时才能完成。

有人建议我进行定期COMMIT,即在每次删除表A的记录(包括在子表中删除任何后续记录)时都进行一次COMMIT。

我知道定期提交将保持撤消日志大小较小,但是否存在性能改进?我会看到脚本完成所需时间的改善吗?


1
撤销日志是一个问题,但对我来说主要的权衡似乎是DELETE脚本可能失败的机会与每个记录的提交开销之间的折衷。我建议在删除一定批次的记录后进行提交可能是一个不错的主意。如果您的DELETE脚本失败,则可以从失败的批次重新开始,而不必回滚整个庞大的事务。 - Tripp Kinetics
那位建议者如何回答这些问题,为什么? - mustaccio
我发现这篇文章很有趣。它甚至暗示了常规的COMMIT会导致更大的重做文件,尽管这是关于9i的,而我正在使用10g。 - Junaid
1个回答

6
频繁提交代码不会提高代码的性能。进行大量中间提交可能会通过强制你花更多时间等待同步操作来降低你的代码速度。如果你在中途提交,你很可能需要编写相当数量的代码来确保你的代码是完全可重启的。
你有AWR或statspack快照,或跟踪文件显示了实际等待的情况吗?30个小时无法完成任何操作似乎不合理。这将导致我强烈怀疑你缺少某些索引,这些索引会导致级联删除每次删除一行时都要进行全表扫描。修复缺失的索引或执行多行删除以减少进行全表扫描的频率似乎更有可能提高性能,而不是担心何时提交更改。

1
我不同意你关于评论的第一部分。如果删除需要30个小时,那么在批处理过程中进行一些中间提交是一个好的解决方案。在这段时间内发生事故(撤消、断开连接等)的概率很高,回滚将是巨大的。进行一些提交不会改善或降低性能,但它会使其更加安全。 - eliatou
@eliatou - 如果您编写代码使您的进程可重启,那么在30小时的过程中进行临时提交确实可以更轻松地重新启动进程,如果它在中途出现错误。虽然如此,这并不与我所说的相矛盾。它不会改善您的代码性能,在一般情况下会增加一些小的惩罚。当然,这种惩罚可能是值得的,但它是一种惩罚。30小时对我来说是如此之长,以至于我会在考虑添加可重启性之前专注于调整它。 - Justin Cave
感谢 @JustinCave 和 eliatou。我没有AWR报告,但你们的建议很有道理。关于索引,大部分表都被正确地索引了,但有几个表使用外键组成主键,每个列都有单独的索引(表本身没有主键)。这些是大表格,我注意到即使是从该表中选择数据也需要很长时间(即加载所有数据需要数小时)。因此,我想知道是否会导致延迟。 - Junaid
无论如何,我已经添加了一些提交并再次运行脚本,让我们看看需要多长时间。 - Junaid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接