优化 Hibernate 序列 ID 生成
Posted
技术标签:
【中文标题】优化 Hibernate 序列 ID 生成【英文标题】:optimise Hibernate Sequence ID generation 【发布时间】:2013-02-26 23:54:22 【问题描述】:我在尝试将 Hibernate 与不支持 AUTO_INCREMENT (http://scn.sap.com/thread/3238906) 的 SAP HANA In-Memory 数据库连接时遇到了一些性能问题。
所以我已将 Hibernate 设置为使用序列来生成 ID。
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="myseq")
@SequenceGenerator(name="myseq",sequenceName="MY_SEQ",allocationSize=1)
但是当我插入大量记录(例如,40000)时,Hibernate 首先生成 ID。它看起来像:
DEBUG Thread-1 org.hibernate.SQL - select MY_SEQ.nextval from DUMMY
DEBUG Thread-1 org.hibernate.id.SequenceGenerator - Sequence identifier generated: BasicHolder[java.lang.Long[92080]]
DEBUG Thread-1 org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 92080, using strategy: org.hibernate.id.SequenceHiLoGenerator
DEBUG Thread-1 org.hibernate.SQL - select MY_SEQ.nextval from DUMMY
DEBUG Thread-1 org.hibernate.id.SequenceGenerator - Sequence identifier generated: BasicHolder[java.lang.Long[92081]]
DEBUG Thread-1 org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 92081, using strategy: org.hibernate.id.SequenceHiLoGenerator
只有在所有的 ID 生成之后,它才开始实际插入。
总共插入 40000 条记录(通过网络到远程数据库)大约需要 5 分钟,这对于内存数据库来说非常慢。我认为这是因为 Hibernate 为 ID 逐一选择下一个值:
send a request to database
get id
send next request
...
我想加快 ID 生成速度,但不幸的是,我对如何改进它的工作了解不够。我搜索了可能的解决方案,发现了以下想法:
1) 在插入语句中调用 sequence.nextval。但是,Hibernate 团队表示这是不可能的:https://forum.hibernate.org/viewtopic.php?f=1&t=932506
2) 使用 SequenceHiLoGenerator。这可能是一个解决方案,但我不明白如何设置它......如果我写
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="myseq")
@SequenceHiLoGenerator(name="myseq",sequenceName="MY_SEQ",allocationSize=1),
Eclipse 中出现“无法从 SequenceHiLoGenerator 转换为注释”错误
3) 在插入时编写数据库触发器。但是,对我来说,这似乎是一个糟糕的解决方案,因为我想要一个通用的 Hibernate 方言与任何数据库实例一起工作。而且我不知道如何将这样的触发器包含在 Hibernate Dialect 中。
您会建议哪种解决方案?您还有其他想法吗?
我将真诚地感谢任何有关此问题的帮助。如果有人可以提供一些解决方案或文档,甚至提供更详细的解决方案路径,那就太好了。
非常感谢您。
【问题讨论】:
【参考方案1】:序列中的值被一个一个地取出,因为allocationSize被设置为1。allocationSize
的默认值是50,这已经好很多了。在这种特殊情况下,如果插入 40000 条记录是典型用例,则使用高于该值的值可能是有意义的。
如果创建序列的脚本是自写的(而不是 Hibernate 编写的),INCREMENT BY
的值应该与 allocationSize
的值相同。
【讨论】:
我不确定这是否正确。见this question。 如果您不确定,请尝试一下。当一个接一个地分配有问题时,一次性分配更多可能会有所帮助。 我尝试了'allocationSize=1000',性能得到了提升。序列的生成速度足够快。然而,数据库仍然很慢——本地数据库每秒大约 500 次插入——这对于内存数据库来说是非常糟糕的。但这应该是另一个问题/问题。以上是关于优化 Hibernate 序列 ID 生成的主要内容,如果未能解决你的问题,请参考以下文章
用于从序列生成 id 的 Oracle 触发器的 HIbernate 问题
Hibernate 5 ID AUTO 生成类型为 Oracle 作为序列和 MySQL 作为身份
如何使用 @ID 和 @GeneratedValue 从 Hibernate + JPA 中的序列中获取 Oracle 生成的值