一尘不染

为什么默认情况下禁用休眠批处理/ order_inserts / order_updates?

hibernate

为何默认禁用hibernate批处理/ hibernate.order_updates /
hibernate.order_inserts?启用批量大小为50时有什么缺点吗?与order_updates /
order_inserts参数相同。有没有不启用此功能的用例?使用此功能是否会对性能产生影响?

我只能看到这些设置在需要减少查询数量时很有用,这在应用程序和数据库服务器之间的延迟很高的云环境中尤其必要。


阅读 1267

收藏
2020-06-20

共1个答案

一尘不染

通常将设置batch size为合理的大小order_insertorder_updatestrue可以显着提高性能。

在我所有的项目中,我都使用以下配置作为基础:

hibernate.jdbc.batch_size = 100
hibernate.order_inserts   = true 
hibernate.order_updates   = true
hibernate.jdbc.fetch_size = 400

但是, 是的 - 使用批处理可能会 影响内存 。但这取决于jdbc驱动程序。

例如,Oracle
JDBC驱动程序为每个缓冲区创建内部缓冲区PreparedStatement并重用这些缓冲区。如果调用简单更新语句,则使用ps.setInt(1, ...)ps.setString(2, ...)等设置一些参数,并且Oracle将此值转换为某些字节表示形式,并存储在与此PreparedStatement和连接关联的缓冲区中。

但是,当您PreparedStatement使用大小为100的批次时,此缓冲区将大100倍。如果您有一些连接池,例如50个连接,则可能有50个这样的大缓冲区。而且,如果您有100个使用批处理的不同语句,则所有此类缓冲区都会对内存产生重大影响。启用批处理大小后,它将成为全局设置-
Hibernate会将其用于所有插入/更新。

但是我发现,在所有项目中,性能的提高对内存的影响更为重要,这就是为什么我将其batchsize=100用作默认值。

使用order_insertsorder_updates我认为默认情况下禁用这些设置,因为这些设置仅在启用批处理时才有意义。取消批处理后,这些排序只是开销。

您可以在Oracle白皮书中找到更多信息:

http://www.oracle.com/technetwork/topics/memory.pdf

“语句批处理和内存使用”部分中

====编辑2016.05.31 ====

一个词order_insertsorder_udpates属性。可以说我们拥有实体AB并以这种方式持久保存6个对象:

session.save(A1);  // added to action queue
session.save(B1);  // added to action queue
session.save(A2);  // ...
session.save(B2);  // ...
session.save(A3);  // ...
session.save(B3);  // ...

经过以上执行:

  • 这6个对象已生成标识符
  • 这6个对象连接到会话(StatefulPersistenceContext:entityByKey,entityEntries等。/Hib.v3/)
  • 将这6个对象以相同的顺序添加到ActionQueue中:[A1,B1,A2,B2,A3,B3]

现在,考虑2种情况:

情况1: order_inserts = false

在刷新阶段,hibernate执行 6条插入 语句:

ActionQueue = [A1, B1, A2, B2, A3, B3]
insert into A - (A1)
insert into B - (B1)
insert into A - (A2)
insert into B - (B2)
insert into A - (A3)
insert into B - (B3)

情况2: order_inserts = true允许批处理

现在,在刷新阶段,hibernate执行 2个批处理插入 语句:

ActionQueue = [A1, A2, A3, B1, B2, B3]
insert into A -  (A1, A2, A3)
insert into B -  (B1, B2, B3)

我针对Hibernate v3进行了调查,我认为Hibernate v4以相同的方式使用ActionQueue。

2020-06-20