Hibernate 批处理插入如何工作?

Pra*_*wal 3 mysql hibernate batch-insert hibernate-batch-updates

有人可以解释我如何

hibernate.jdbc.batch_size=1000 
Run Code Online (Sandbox Code Playgroud)

if (i % 100 == 0 && i>0) {
                    session.flush();
                    session.clear();
                }
Run Code Online (Sandbox Code Playgroud)

一起工作?...

Aba*_*s A 5

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

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

想象一下以下代码块:

for(Entity e : entities){
session.save(e);
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

因此,设置此属性并不能防止内存耗尽。

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

当你写:

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

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

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

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

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

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

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


Dra*_*vic 1

hibernate.jdbc.batch_size确定执行的最大批处理大小。如果在达到指定的批量大小(同一表的待处理插入或更新语句的数量)之前执行隐式或显式刷新,则所有待处理语句将打包在一批中,并重新开始语句的“累积”。

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