【问题标题】:Spring,Hibernate - Batch processing of large amounts of data with good performanceSpring,Hibernate - 批量处理大量数据,性能好
【发布时间】:2012-02-06 16:04:10
【问题描述】:

假设您在数据库中大约有大量数据。 〜100Mb。我们需要以某种方式处理所有数据(更新或导出到其他地方)。如何以良好的性能执行此任务?如何设置交易传播?

示例 1#(性能不佳):

@Singleton
public ServiceBean {

 procesAllData(){

   List<Entity> entityList = dao.findAll();

   for(...){
     process(entity);
   }

 }

 private void process(Entity ent){
  //data processing    
  //saves data back (UPDATE operation) or exports to somewhere else (just READs from DB)
 }

}

这里有什么可以改进的?

在我看来:

  1. 我会设置休眠批处理大小(请参阅休眠文档以了解批处理)。
  2. 我会将 ServiceBean 分成两个具有不同事务设置的 Spring bean。方法 processAllData() 应该用完事务,因为它处理大量数据并且潜在的回滚不会“快速”(我猜)。方法流程(实体实体)将在事务中运行 - 在一个数据实体的情况下进行回滚没什么大不了的。

你同意吗?有什么建议吗?

【问题讨论】:

  • 当你说“表现不佳”时,这是一个真实的程序,还是只是猜测?
  • @Skaffman :它的真正程序,我只是将我们的实现抽象到上面的示例中。 1)当操作超过事务到期时间时,会自动回滚-> thats bad, batch never completes. So thats 为什么我认为不需要该事务。 2) 我们不需要 Oracle 中的大量重做日志。

标签: spring hibernate transactions batch-processing large-data


【解决方案1】:

这里有 2 个基本策略:

  1. JDBC 批处理:设置 JDBC 批处理大小,通常在 20 到 50 之间 (hibernate.jdbc.batch_size)。如果您正在混合和匹配对象 C/U/D 操作,请确保您已将 Hibernate 配置为订购插入和更新,否则它不会批处理(hibernate.order_insertshibernate.order_updates)。在进行批处理时,必须确保您 clear()Session,这样您就不会在大型事务期间遇到内存问题。
  2. 连接的 SQL 语句:实现 Hibernate Work 接口并使用您的实现类(或匿名内部类)针对 JDBC 连接运行本机 SQL。通过分号连接手动编码的 SQL(适用于大多数数据库),然后通过 doWork 处理该 SQL。此策略允许您使用 Hibernate 事务协调器,同时能够利用原生 SQL 的全部功能。

您通常会发现,无论您获得 OO 代码的速度有多快,使用连接 SQL 语句等 DB 技巧都会更快。

【讨论】:

    【解决方案2】:

    这里有几件事要记住:

    1. 使用 findAll 方法将所有实体加载到内存中可能会导致 OOM 异常。

    2. 您需要避免将所有实体附加到会话 - 因为每次 hibernate 执行刷新时,它都需要对每个附加实体进行脏检查。这将很快使您的处理停止。

    Hibernate 提供了一个无状态会话,您可以将其与可滚动结果集一起使用,以逐个滚动实体 - 文档 here。然后,您可以使用此会话更新实体,而无需将其附加到会话。

    另一种选择是使用有状态会话,但定期清除会话,如 here 所示。

    我希望这是有用的建议。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多