当前位置: 首页 > 知识库问答 >
问题:

优化Hibernate序列ID生成

胡星汉
2023-03-14

我在尝试将HiberNate与SAP HANA In-Memory数据库连接时遇到了一些性能问题,该数据库不支持AUTO_INCREMENT(http://scn.sap.com/thread/3238906)。

因此,我将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

2) 使用SequenceHiLoGenerator。这可能是一个解决方案,但我不知道如何设置它…如果我写

  @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="myseq") 
  @SequenceHiLoGenerator(name="myseq",sequenceName="MY_SEQ",allocationSize=1),

我在 Eclipse 中收到“无法从 SequenceHiLoGenerator 转换为注释”错误

3)在插入上编写一个数据库触发器。然而,对我来说,这看起来是一个糟糕的解决方案,因为我想让一个通用的HiberNate Dialect与任何数据库实例一起工作。我不知道如何将这样的触发器包含到HiberNate Dialect中。

您会建议哪种解决方案?你还有其他想法吗?

我将真诚地感谢对这个问题的任何帮助。如果有人可以提供一些解决方案或文档,甚至只是更详细的解决方案途径,那就太好了。

先谢谢你了。

共有1个答案

梁丘安晏
2023-03-14

因为allocationSize设置为1,所以从sequence中逐个获取值。< code>allocationSize的默认值是50,这已经好得多了。在这种特殊情况下,如果插入40000条记录是典型的用例,那么使用更高的值可能是有意义的。

如果创建序列的脚本是自己编写的(而不是由Hibernate编写的),则< code>INCREMENT BY的值应该与< code>allocationSize的值相同。

 类似资料:
  • 问题内容: 尝试将Hibernate与SAP HANA内存数据库连接时遇到一些性能问题,该数据库不支持AUTO_INCREMENT(http://scn.sap.com/thread/3238906)。 因此,我将Hibernate设置为使用序列进行ID生成。 但是,当我插入大量记录(例如40000)时,Hibernate首先会生成ID。看起来像: 并且只有在生成所有ID之后,它才开始实际插入。

  • 问题内容: 我的数据库是Oracle,我的id列值是Oracle序列,此序列由触发器执行,因此,在插入每一行之前,此触发器使用此序列来获取id值。因此,我对应该在实体类中定义哪个ID策略生成感到困惑。 要么 要么 真的很困惑,有人可以阐明这个问题吗?请清楚解释。 问题答案: 我还有一个projet,其中有一个Oracle DB将数据提供给我的@Entity类。如您所说,序列通过触发器为表的PK生成

  • 问题内容: 我有一个具有以下定义的类: 当我们在Jboss 4.2.3上运行它时,它可以正常工作并生成正确的ID(从1000+开始) 现在我们转到jboss 7.1.1,它会生成负ID!(从-498开始,然后上升) 知道为什么会发生这种情况吗? 问题答案: 从JBoss 6.1迁移到JBoss 7.1时遇到了这个问题。 根据JBoss AS 7.1 JPA文档(https://docs.jboss

  • 环境:Spring Boot 2.2.6 启动程序:spring-boot-starter-data-jpa,*-thymeleaf,*-web,*-Tomcat,*-test 其他依赖项:mariadb-java-client 2.6.0,spring-boot-devtools(管理),lombok(管理) DB mariadb:10.4 Hibernate方言:mariadb103 使用内部

  • 问题内容: 我有一个用序列生成的主键定义的实体: 我正在使用PostgreSQL,并且此密钥定义为序列号。根据PostgreSQL 退货 当我执行create()来持久化此实体的实例时,我在日志中看到以下内容(不相关的内容已被删除): 05 15:15:26.948 org.hibernate.id.enhanced.SequenceStructure [DEBUG]-获得的序列值:1604 05

  • 我一整天都在尝试从JPA/Hibernate的Postgres获取序列,但它给了我所有的时间: 信息:Hibernate:调用tb_cdr_id_seq的下一个值警告:SQL错误: 0,SQLState: 42601错误:错误:语法错误在或附近“调用”严重:javax.persistence.持久性异常:org.hibernate.exception.SQLGrammar异常:无法提取结果集 Po