【问题标题】:Hibernate: Why should I manually flush() even if I set batch_size in configuration file?Hibernate:即使我在配置文件中设置了 batch_size,为什么还要手动刷新()?
【发布时间】:2017-07-10 08:58:34
【问题描述】:

我正在学习使用 java 的 hibernate 5.2.10。我开始使用一些在线教程,但遇到了以下问题。

在使用批处理的时候,我看到的所有教程都先在配置文件中设置hibernate.jdbc.batch_size。之后的代码类似这样:

Session session = SessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<1000000; i++ ) 
{
    Student student = new Student(.....);
    session.save(employee);
    if( i % 50 == 0 ) // Same as the JDBC batch size
    { 
        //flush a batch of inserts and release memory:
        session.flush();
        session.clear();
    }
}
tx.commit();
session.close();

我为什么要手动执行flush()clear()?这不是应该由hibernate自动完成的,因为我已经在配置文件中设置了hibernate.jdbc.batch_size吗?

对我来说,我好像是手动批处理我的操作,那么为什么我必须设置 hibernate.jdbc.batch_size 的值呢?

【问题讨论】:

    标签: java hibernate batching


    【解决方案1】:

    在配置中指定 JDBC batch_size 值与手动控制持久性上下文的刷新/清除是两种独立的策略,用途截然不同。

    flush()clear() 配对使用的主要目标是在保存学生记录时最大限度地减少PersistenceContext 使用的Java 应用程序端的内存消耗。重要的是要记住,当您使用有状态的 Session 时,如您的示例所示,Hibernate 在内存中维护实体的附加/托管副本,因此定期清除并将其刷新到数据库以避免运行很重要内存不足或影响性能。

    JDBC batch_size 设置本身会影响实际驱动程序将语句刷新到数据库的频率,以提高性能。让我们举一个稍微修改的例子:

    Session session = sessionFactory.openSession();
    try {
      session.getTransaction().begin();
      for ( int i = 0; i < 10000; ++i ) {
        Student student = new Student();
        ...        
        session.save( student );
      }
      session.getTransaction().commit();
    }
    catch( Throwable t ) {
      if ( session.getTransaction().getStatus() == TransactionStatus.ACTIVE ) {
        session.getTransaction().rollback();
      }
      throw t;
    }
    finally {
      session.close();
    }
    

    如您所见,我们在这里没有使用flush()clear()

    这里发生的情况是,当 Hibernate 在提交时执行刷新时,驱动程序将批量发送 batch_size 数量的插入到数据库,而不是单独发送一个。因此,如果 batch_size 为 250,它只会发送 40 个数据包,而不是发送 10,000 个网络数据包。

    现在重要的是要认识到有些因素可以禁用批处理,例如使用基于身份的标识符,如 IDENTITYAUTO_INCREMENT。为什么?

    这是因为为了让 Hibernate 将实体存储在 PersistenceContext 中,它必须知道实体的 ID,并且在使用基于 IDENTITY 的标识符生成时获取该值的唯一方法是实际查询数据库以获取之后的值每个插入操作。因此,不能对插入进行批处理。

    这正是执行批量插入操作的人经常观察到性能不佳的原因,因为他们没有意识到他们选择的标识符生成策略可能产生的影响。

    当您想要优化批量加载时,最好使用某种类型的缓存序列生成器或某些手动应用程序分配的标识符。

    现在回到您使用flush()clear() 的示例,标识符生成策略也存在同样的问题。如果您希望将这些操作批量/批量发送到数据库,请注意您用于 Student 的标识符策略。

    【讨论】:

      【解决方案2】:
        //flush a batch of inserts and release memory:
          session.flush();
          session.clear();
      

      您应该调用flush() 方法来强制生成sql 查询并执行它们。如果您不手动调用 flush() ,如果由休眠调用并提交事务时间。

      您应该调用 clear() 方法从持久性上下文中删除有关实体的信息以避免 OutOffMemeoryException ,因为您可能有一个包含大量实体的 butch,它们可能会消耗大量内存。

      您应该手动控制批处理操作,因为并非所有休眠操作都需要批处理模式。

      “我为什么要手动执行 flush() 和 clear()?这不是应该由 hibernate 自动完成的事情,因为“ - 主要是,hibernate 在提交时执行此操作。方法 flush() 和 clear() 独立于使用 batch_size ,无论你是否有批处理模式,你都可以调用它们。

      当你在 dao 方法内部调用 N 次 flush() - 当你需要实体和 db 级别之间的同步,并调用 flush() - 当你不再使用实体并且想要干净的会话。

      从您的示例中,您有 1000000 个元素。无需调用 flush 和 clear 即可将所有 1000000 个元素的信息保存在一级缓存中。您在循环中的每个新迭代中将一个一个新实体添加到会话上下文中,但是在批处理准备好/准备好之后您不需要此信息,这就是为什么您应该调用 flush , clear - 以删除您不再需要的信息.

      【讨论】:

      • 我明白这一切。我无法理解的是为什么我要在我的配置文件中设置hibernate.jdbc.batch_size 的值?如果我手动进行所有批处理,它有什么用?我的意思是如果我没有设置这个值怎么办?会有什么改变吗?
      • 我如何准确地给休眠标记以执行此批处理?每次我保存batch_size 元素数量时,我都手动执行flush()clear(),我在代码中看不到创建或处理批处理的任何地方,除了正在创建批处理的事实,因为我的if 声明和我的flush()clear() 在其中调用。我仍然很奇怪为什么要这样做。我的意思是如果我没有在 hibernate 的配置文件上设置这个值并且我的代码保持不变怎么办?会有什么改变吗?
      • 我看到了您的更新,但您似乎没有理解我的问题。我知道如果不使用flush()clear() 我会得到OutOfMemory 错误,但这不是我的问题。我的问题是为什么要在我的配置文件中设置batch_size 的值?它有什么用?您提到它用于提交时间。这是否意味着使用flush()clear() 独立于批处理?所以我使用flush()clear() 来防止OutOfMemory 错误?我使用batch_size 进行批处理,以批处理的形式更有效地提交我的更改?
      【解决方案3】:

      回答您在描述中提出的问题,正如我所研究的那样,flush()-ing 批处理/事务与 commit()-ing 事务不同。

      您在每 50 个块后刷新事务,这意味着您正在将事务同步作为 50 个批次到数据库。50 个块已与数据库同步但尚未提交。 但是当您在配置文件中定义批处理大小时,您是在告诉 Hibernate commit 40 的批处理(假设您在 conf 文件中设置了批处理大小 40。)

      【讨论】:

        猜你喜欢
        • 2017-10-10
        • 1970-01-01
        • 2012-10-26
        • 1970-01-01
        • 2020-09-18
        • 2016-11-01
        • 1970-01-01
        • 2011-07-01
        • 2010-12-25
        相关资源
        最近更新 更多