在表插入中提交每 x 行

Posted

技术标签:

【中文标题】在表插入中提交每 x 行【英文标题】:Committing every x rows in table insert 【发布时间】:2017-08-17 10:31:19 【问题描述】:

我正在从 JDBC 连接到 静态 Oracle 12c 数据库的表中写入大量行(约 2000 万行)。我想每 10,000 行提交一次以防止回滚,这样如果出现错误,我可以有效地从上次提交中重新启动插入命令。

我可以使用 JDBC 做到这一点的最有效(时间和资源)方式是什么?

请注意,这将是来自大型基础表连接的 INSERT INTO SELECT 语句。因此,游标会大大减慢插入语句的速度——它们真的是最好的解决方案吗?

【问题讨论】:

我不确定您在问什么 - 如何将 select 部分限制为仅 10,000 行?如何识别它们是哪些行,和/或排除先前插入的行?你为什么不把它作为一个 single insert ... select 语句在最后一个提交 - 这样你就不必担心重新启动 - 这将是最有效的(只要你有足够的撤消空间)?为什么单个批次会出现 10,000 个错误,如果出现错误,您将如何解决? 由于插入的行数较多,插入需要很长时间,不幸的是这需要在一个相当短的窗口中处理。如果插入出现问题并且我们丢失了所有进度,我们将不得不从头开始,而且我不知道我们是否有足够的资源(撤消空间)来一次性处理这一切。这能回答你的问题吗? 有点,但是批处理和提交会更慢(如果没有错误) - 可能慢得多,具体取决于您如何确定每批中的 10,000 个。我仍然不确定您需要帮助的哪一点,或者您是如何考虑使用光标的。 我的问题指的是如何最小化速度时间。我很高兴插入速度相当慢,只要它稳定并最大限度地减少资源消耗:如果事实证明我们没有资源一次性处理这一切,我将失去进度插入,并且必须重新开发语句背后的逻辑。 始终建议使用一次性方法,INSERT 撤消操作相对较少。如果你真的需要打破它,你可以看看bulk collectlimit + forall 【参考方案1】:

单个insert into ... select ... 通常是最有效的(如果您的系统能够处理它)。

如果您真的想将其拆分,可以使用诸如

之类的方案
while <rows still need inserting>
    insert into x
    select from y where (y is not x) and rownum < 10000;
    commit

其中 (y is not in x)not in()NOT EXISTS() 或其他此类机制,仅适用于尚未插入的选定行。

【讨论】:

以上是关于在表插入中提交每 x 行的主要内容,如果未能解决你的问题,请参考以下文章

NHibernate Insert 正在提交,但对象未保存在表中

第一个表单提交插入行后续提交更新同一行

如何使用 Jquery 在表上附加输入类型提交元素并绑定它?

jQuery clone() FireFox 错误 - 无法提交克隆的表单

提交时无法在数据库中插入时间戳

0 行删除/更新/插入需要在 ORACLE 中提交?