Spring、Hibernate—批处理大量数据,性能良好

Spring、Hibernate—批处理大量数据,性能良好,spring,hibernate,transactions,batch-processing,large-data,Spring,Hibernate,Transactions,Batch Processing,Large Data,假设数据库中有大约100Mb的大量数据。我们需要以某种方式处理所有数据(更新或导出到其他地方)。如何以良好的性能执行此任务?如何设置事务传播 示例1(性能不佳): @Singleton 公共服务豆{ procesAllData(){ List entityList=dao.findAll(); 对于(…){ 过程(实体); } } 私有作废流程(实体ent){ //数据处理 //将数据保存回(更新操作)或导出到其他位置(仅从数据库读取) } } 这里可以改进什么 我认为: 我将设置hibern

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

示例1(性能不佳):

@Singleton
公共服务豆{
procesAllData(){
List entityList=dao.findAll();
对于(…){
过程(实体);
}
}
私有作废流程(实体ent){
//数据处理
//将数据保存回(更新操作)或导出到其他位置(仅从数据库读取)
}
}

这里可以改进什么

我认为:

  • 我将设置hibernate批处理大小(有关批处理,请参阅hibernate文档)
  • 我将ServiceBean分成两个具有不同事务设置的Springbean。方法processAllData()应该用完事务,因为它使用大量数据进行操作,并且可能的回滚不会“快速”(我猜)。方法进程(实体)将在事务中运行——对于一个数据实体来说,回滚并不是什么大事

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

    这里有几点需要记住:

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

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

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

    另一种替代方法是使用有状态会话,但要定期清除会话,如图所示


    我希望这是一个有用的建议。

    这里有两个基本策略:

  • JDBC批处理:设置JDBC批处理大小,通常在20到50之间(
    hibernate.JDBC.batch\u size
    )。如果要混合和匹配对象C/U/D操作,请确保已将Hibernate配置为订购插入和更新,否则它将不会批处理(
    Hibernate.order\U inserts
    Hibernate.order\U updates
    )。在执行批处理时,必须确保
    clear()
    您的
    会话
    ,以便在大型事务期间不会遇到内存问题
  • 连接SQL语句:实现Hibernate
    Work
    接口,并使用实现类(或匿名内部类)对JDBC连接运行本机SQL。通过分号连接手工编码的SQL(适用于大多数数据库),然后通过
    doWork
    处理该SQL。此策略允许您使用Hibernate事务协调器,同时能够充分利用本机SQL的强大功能

  • 您通常会发现,无论您的OO代码有多快,使用诸如连接SQL语句之类的DB技巧都会更快。

    当您说“性能差”时,这是一个真实的程序,还是您只是在猜测?@Skaffman:它是真实的程序,我刚刚将我们的实现抽象到上面的示例中。1) 当操作花费的时间超过事务到期时间时,会自动回滚->该
    s错误,批处理永远不会完成。因此
    s这就是我认为没有必要进行交易的原因。2) 我们不需要Oracle中的大量重做日志。
    @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)
     }