我认为你可以在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正常工作。
请勿使用可更新的结果集。表演将是糟糕的,保证。
是执行数据库中所有更新所需的信息吗? (使用公式)或者当你说要完成一些处理时,这是因为更新所需的一些信息是本地的? – xQbert
嗨。否更新的信息不包含在数据库中。我必须读取数据行,然后调用外部服务来检索计算值,然后使用计算值更新行的3个字段。 – Gilles
@Gilles你需要多长时间才能完成这项工作?您将要将数据提取到java中,并为每一行调用外部服务,然后更新数据库。假设您可以每行10毫秒完成这项工作,我怀疑您可以完成这项工作,但仍需9.25天才能完成此过程。从那里扩展它。如果每行需要100ms,现在是92.5天。如果这样做,你最好知道你在做什么。 – unleashed