使用Java处理数百万个数据库记录

时间:2012-10-19 17:17:11

标签: java spring jdbc batch-processing spring-batch

我需要编写批处理作业,该作业从数据库表中提取行并基于某些条件,写入其他表或使用特定值更新此行。我们使用spring和jdbc来获取结果集,并使用计划每周运行的独立java程序迭代并处理记录。我知道这不是正确的方法,但我们必须将其作为临时解决方案。随着记录增长到数百万,我们最终会出现内存异常,所以我知道这不是最好的方法。

你们中的任何人都可以推荐一种处理这种情况的最佳方法吗?

使用线程并为每个线程获取1000条记录并并行处理它们?

(OR)

使用任何其他批处理机制来执行此操作(我知道有弹簧批但从未使用过它)

(OR)

还有其他想法吗?

4 个答案:

答案 0 :(得分:7)

您已经知道,您无法将100万行带入内存并对其进行操作。

你必须以某种方式对它们进行分块。

为什么要将它们带到中间层?我会考虑编写存储过程并对数据库服务器上的数据进行操作。把它带到中间层看起来好像没有给你买任何东西。让您的批处理作业启动存储过程并在数据库服务器中就地进行计算。

答案 1 :(得分:6)

  

批处理作业,它从数据库表中提取行并基于某些条件,写入其他表或使用特定值更新此行。

这听起来像你应该在数据库中做的事情。例如,要获取特定行并根据特定条件更新它,SQL具有UPDATE ... WHERE ... statement。要写入另一个表,您可以使用INSERT ... SELECT ...

这些可能会变得相当复杂,但我建议尽一切力量在数据库中执行此操作,因为将数据拉出来过滤它非常慢并且无法实现关系数据库的目的。

注意:请务必先在非生产系统上进行试验,并实施所需的任何限制,以免在不良时间锁定生产表。

答案 2 :(得分:1)

这实际上取决于您处理记录的内容和方式。

但一般来说,你不应该立刻将它们全部加载到内存中,而是使用合理大小的块进行处理。

答案 3 :(得分:0)

同意Brendan Long的意见。但是,我可能仍会尝试在存储过程中选择“数百万”数据集的子集。否则,您将破坏数据库的事务日志。只需确保您定期提交插入或更新。

如果您不想在Stored proc中执行此操作,只需让spring批量加载您希望以某个固定块大小操作的记录的键(使用游标/分页阅读器),但获取存储过程做实际的工作。这样,您可以最大限度地减少传递到中间层的数据,同时仍然可以获得spring批处理和db在处理数据方面的性能。