JDBC更新Oracle数据库上的数百万条记录

时间:2017-05-11 19:39:08

标签: oracle jdbc

我有设计问题。我有一个包含数百万条记录的数据库,我需要更新。

我们将使用JDBC,因为我们必须进行一些处理来计算新的字段值。

这是一次性的,我不再需要它了。所以我在想一些简单的事情。我想创建新表并删除旧表,但DBA不希望这样,因为对存储的需求会很大。

我必须处理大约8千万行,并且每行要更新3个字段。

使用setFetchSize(1000)的简单jdbc方法是否可行?

我的意思是从mutable中选择a,b,c进行更新; 更新......

JDBC程序是否能够支持工作负载?

我也在考虑使用SpringBatch或EasyBatch。但我想知道是否值得一次性调查时间(以及一些非常短的时间表)。

您对此有何体验?

1 个答案:

答案 0 :(得分:0)

我认为你可以在JDBC中做到这一点。我建议如下:

  • 创建两个或三个线程。每个线程都执行以下操作
  • 创建连接。
  • 创建一个准备好的语句,用于检索行的不相交子集
  • 将提取大小设置为100左右。绝对不到1000。
  • 创建更新声明
  • 执行查询
  • 迭代结果集
  • 为每行添加批处理以更新行
  • 获取大小行后执行批处理

让我们假设获取大小为100.第一次执行将进行往返,这需要时间。在发生这种情况时,请运行另一个线程。当执行返回处理时,接下来的100行不会进行数据库往返。已经提取了行并且正在对更新进行批处理,因此这不会进行数据库往返。在100行之后执行将进行往返的批处理,因此将切换线程。然后它将获取100多行,这将切换线程。我不确定两个或三个线程是否最佳,但如果我不得不猜测我会尝试三个。

但是上面假设机器只有一个硬件线程,这是不正确的。大多数CPU支持12个或更多硬件线程,因此我实际上会使用30个左右的线程,具体取决于硬件可以支持的内容。即使有多个CPU,您也可能不需要超过50个线程,因为这会开始在数据库中引入争用。

以上假设外部服务快速,比数据库快得多。如果没有,则处理每一行将等待外部服务。在那种情况下更多线程。由于更新将更快地打到数据库,因此数据库中的线程争用不再是一个问题。

将查询结果划分为不相交的子集的一种方法如下:

SELECT c1, c2, etc, row 
FROM (SELECT c1, c2, etc, ROWNUM FROM ...) 
WHERE MOD(row, number_of_partitions) = ?

然后将查询参数从0设置为number_of_partitions - 1,每个线程一个。您必须将此作为子查询才能使ROWNUM正常工作。

不要使用可更新的结果集。表现将是糟糕的,保证。