在表插入中提交每 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 collect
和limit
+ 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 在表上附加输入类型提交元素并绑定它?