2017-05-11 193 views
0

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

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

这是一回事,我不再需要它了。所以我在想简单的事情。我想创建新表并删除旧表,但DBA不想这样做,因为对存储的需求会很大。我将不得不处理大约80百万行,并为每行更新3个字段。

简单的jdbc方法,例如setFetchSize(1000)会起作用吗?

我的意思是从可变更新中选择a,b,c; 然后更新...

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

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

您对此有何体会?

+0

是执行数据库中所有更新所需的信息吗? (使用公式)或者当你说要完成一些处理时,这是因为更新所需的一些信息是本地的? – xQbert

+0

嗨。否更新的信息不包含在数据库中。我必须读取数据行,然后调用外部服务来检索计算值,然后使用计算值更新行的3个字段。 – Gilles

+1

@Gilles你需要多长时间才能完成这项工作?您将要将数据提取到java中,并为每一行调用外部服务,然后更新数据库。假设您可以每行10毫秒完成这项工作,我怀疑您可以完成这项工作,但仍需9.25天才能完成此过程。从那里扩展它。如果每行需要100ms,现在是92.5天。如果这样做,你最好知道你在做什么。 – unleashed

回答

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正常工作。

请勿使用可更新的结果集。表演将是糟糕的,保证。

相关问题