【问题标题】:How Hibernate Batch insert works?Hibernate 批量插入是如何工作的?
【发布时间】:2018-01-22 01:26:21
【问题描述】:

谁能解释一下

hibernate.jdbc.batch_size=1000 

if (i % 100 == 0 && i>0) {
                    session.flush();
                    session.clear();
                }

一起工作? ...

【问题讨论】:

标签: mysql hibernate batch-insert hibernate-batch-updates


【解决方案1】:

Hibernate 属性 hibernate.jdbc.batch_size 是 hibernate 优化插入或更新语句的一种方式,而刷新循环是关于内存耗尽的。

当您尝试保存实体 hibernate fire 1 insert 语句时没有批量大小,因此如果您使用大集合,则对于每个 save hibernate fire 1 语句

想象一下下面这段代码:

for(Entity e : entities){
session.save(e);
}

这里 hibernate 将在您的集合中为每个实体触发 1 个插入语句。如果您的集合中有 100 个元素,那么将触发 100 个插入语句。 这种方法效率不高主要有两个原因:

  • 1) 您的一级缓存呈指数级增长,您可能很快就会收到OutOfMemoryException
  • 2) 由于每个语句的网络往返,您会降低性能。

hibernate.jdbc.batch_size 和刷新循环有 2 个不同的目的,但是是互补的。

Hibernate 使用第一个来控制批处理的实体数量。在 Hibernate 中使用 java.sql.Statement.addBatch(...)executeBatch() 方法。

所以 hibernate.jdbc.batch_size 告诉 hibernate 在调用 executeBatch() 之前它必须调用多少次 addBatch()

所以设置这个属性并不会阻止你的内存耗尽。

为了处理内存,您必须定期刷新会话,这就是刷新循环的目的。

当你写的时候:

for(Entity e : entities){
if (i % 100 == 0 && i>0) {
                    session.flush();
                    session.clear();
                }
}

您是在告诉 hibernate 每 100 个实体刷新和清除会话(释放内存)。

那么现在两者之间的联系是什么?

为了达到最佳效果,您必须定义您的 jdbc.batch_size 和您的刷新参数相同。

如果您定义的刷新参数低于您选择的 batch_size,那么休眠将更频繁地刷新会话,因此它将创建小批量,直到达到 btach 大小 效率不高

当 2 个相同时,如果集合的大小不是 batch_size 的倍数,则休眠将只执行最佳大小的批次,最后一个除外。

您可以查看以下post 了解有关最后一点的更多详细信息

【讨论】:

  • id生成策略限制等其他需求呢?
  • by 和你的冲洗参数相同这是否意味着我必须每 50 次坚持做session.flush()?我可以等到整个过程结束后再做flush()吗?
【解决方案2】:

hibernate.jdbc.batch_size 确定要执行的最大批处理大小。如果在达到指定的批大小(the same table 的挂起插入或更新语句的数量)之前执行了隐式或显式刷新,则所有挂起的语句都打包在一个批次中,并重新开始“累积”语句。

因此,在您的示例中,您将执行包含 100 条语句的批处理。或者,例如,如果批处理大小为 100 且模除数为 500,则当刷新操作发生时,您将执行 5 个批处理,每个批处理包含 100 个语句。

【讨论】:

    【解决方案3】:

    批处理允许您将相关的 SQL 语句分组到一个批处理中,并通过一次调用数据库来提交它们。

    我们为什么需要

    请记住,添加到 Statement 或 PreparedStatement 的每个更新都是由数据库单独执行的,这一点很重要。这意味着,其中一些可能会在其中一个失败之前成功。所有成功的语句现在都应用于数据库,但其余的更新可能不会。这可能会导致数据库中的数据不一致。

    为避免这种情况,您可以在事务中执行批量更新。在事务中执行时,您可以确保执行所有更新,或者不执行任何更新。任何成功的更新都可以回滚,以防其中一个更新失败。

    什么是批处理和刷新

    批量大小和冲洗是不同的事情。当您将hibernate.jdbc.batch_size 设置为1000 时,这意味着hibernate 将批量插入或更新到1000 实体。flush 操作可用于在事务提交之前将所有更改写入数据库

    如果您的批处理大小设置为 1000,并且您每 100 个实体刷新一次,Hibernate 将执行 10 次小批量的 100 个插入或更新语句。

    请在此链接下方阅读更多内容:

    http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/batch.html

    Why number of objects being flushed should be equal to hibernate.jdbc.batch_size?

    【讨论】:

      猜你喜欢
      • 2011-02-15
      • 2012-02-16
      • 2015-07-03
      • 2011-07-04
      • 1970-01-01
      • 1970-01-01
      • 2022-11-10
      • 2021-04-23
      • 1970-01-01
      相关资源
      最近更新 更多