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

JDBC在Oracle数据库上更新了数百万条记录,oracle,jdbc,Oracle,Jdbc,我有一个设计问题。我有一个数据库,有数百万条记录需要更新 我们将使用JDBC,因为我们必须进行一些处理来计算新字段的值 这是一次性的,我不再需要它了。所以我在想一些简单的事情。我想创建新表并删除旧表,但DBA不想这样做,因为对存储的需求将是巨大的 我必须处理大约8000万行,每行更新3个字段 以setFetchSize(1000)为例,简单的jdbc方法是否可行 我的意思是从mutable中选择a、b、c进行更新; 然后更新 JDBC程序能够支持工作负载吗 我也在考虑使用SpringBatch或

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

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

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

我必须处理大约8000万行,每行更新3个字段

以setFetchSize(1000)为例,简单的jdbc方法是否可行

我的意思是从mutable中选择a、b、c进行更新; 然后更新

JDBC程序能够支持工作负载吗

我也在考虑使用SpringBatch或EasyBatch。但我想知道是否值得在这方面花时间研究一次(以及一些非常短的时间线)


您对此有何经验?

我认为您可以在JDBC中这样做。我建议如下:

  • 创建两个或三个线程。每个线程执行以下操作
  • 创建一个连接
  • 创建一个准备好的语句,用于检索不相交的行子集
  • 将提取大小设置为100左右。绝对少于1000
  • 创建更新语句
  • 执行查询
  • 迭代结果集
  • 对于每一行,添加批以更新该行
  • 获取大小行后,执行批处理
假设提取大小为100。第一次执行将执行一次需要时间的往返。当这发生时,运行另一个线程。当execute返回处理下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设置为分区的数量-1,每个线程一个。要使ROWNUM正常工作,必须将其作为子查询来执行


不要使用可更新的结果集。性能将非常糟糕,这是有保证的。

进行更新所需的信息是否都包含在数据库中?(使用公式)或者当您说必须进行某些处理时,是因为更新所需的某些信息是本地的?您好。否数据库中不包含更新信息。我必须读取数据行,然后调用外部服务来检索计算值,然后用计算值更新行中的3个字段。@Gilles您需要多长时间才能完成此操作?您将把数据拉入java,并为每一行调用一个外部服务,然后更新数据库。让我们假设您可以在每行10毫秒内完成此操作,我怀疑您是否能够做到这一点,完成此过程仍然需要9.25天。从那里向上延伸。如果每行需要100毫秒,那么现在是92.5天。如果必须这样做的话,你最好知道你在做什么。可能需要找到一种并行的方法。