Why is hibernate batching / order_inserts / order_updates disabled by default?

烈酒焚心 提交于 2019-12-02 20:48:46

Generally setting batch size to resonable size and order_insert, order_updates to true can significantly improve performance.

In all my projects I use this configuration as basis:

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

But, yes - there can be memory impact when using batching. But this depends on jdbc driver.

For example Oracle JDBC driver creates internal buffers for each PreparedStatement and reuses these buffers. If you call simple update statement you set some parameters with ps.setInt(1, ...), ps.setString(2, ...) etc, and Oracle converts this values to some byte representation and stores in buffer associated with this PreparedStatement and connection.

However when your PreparedStatement uses batch of size 100, this buffer will be 100 times larger. And if you have some connection pool with for exapmle 50 connections there can be 50 such big buffers. And if you have 100 different statements using batching all such buffers can have significant memory impact. When you enable batch size it becomes global setting - Hibernate will use it for all insert/updates.

However I found that in all my projects performance gain was more important that this memory impact and that is why I use batchsize=100 as my default.

With order_inserts, order_updates, I think that these are disabled by default, because these settings make sense only when batching is on. With batching set off, these ordering is simply overhead.

You can find more info in Oracle's white paper:

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

in section "Statement Batching and Memory Use".

==== EDIT 2016.05.31 ====

A word about order_inserts and order_udpates property. Lets say we have entities A, B and persist 6 objects this way:

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);  // ...

after above execution:

  • these 6 objects has identifiers generated
  • these 6 objects are connected to session (StatefulPersistenceContext: entitiesByKey, entityEntries, etc. /Hib.v3/)
  • these 6 objects are added to ActionQueue in the same order: [A1, B1, A2, B2, A3, B3]

Now, consider 2 cases:

case 1: order_inserts = false

during flush phase hibernate performs 6 insert statements:

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)

case 2: order_inserts = true, batching allowed

now, during flush phase hibernate performs 2 batch insert statements:

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

I investigated this for Hibernate v3, I think Hibernate v4 uses ActionQueue in the same way.

The documentation here: https://docs.jboss.org/hibernate/stable/orm/userguide/html_single/chapters/batch/Batching.html

says there may be a performance penalty for using these properties. I would assume this is the reason they are not set by default.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!