我有设计问题。我有一个包含数百万条记录的数据库,我需要更新。
我们将使用JDBC,因为我们必须进行一些处理来计算新的字段值。
这是一次性的,我不再需要它了。所以我在想一些简单的事情。我想创建新表并删除旧表,但DBA不希望这样,因为对存储的需求会很大。
我必须处理大约8千万行,并且每行要更新3个字段。
使用setFetchSize(1000)的简单jdbc方法是否可行?
我的意思是从mutable中选择a,b,c进行更新; 更新......
JDBC程序是否能够支持工作负载?
我也在考虑使用SpringBatch或EasyBatch。但我想知道是否值得一次性调查时间(以及一些非常短的时间表)。
您对此有何体验?
答案 0 :(得分:0)
我认为你可以在JDBC中做到这一点。我建议如下:
让我们假设获取大小为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正常工作。
不要使用可更新的结果集。表现将是糟糕的,保证。