Hibernate Sequence Generator查询两次nextval是否为预缓存行为,可否调优?
问题结论
你遇到的两次执行select nextval ('some_sequence')的现象不属于异常,也不是Hibernate预缓存机制的正常表现,是序列生成器参数和数据库序列配置不匹配导致的额外调用。
根因分析
@SequenceGenerator注解的allocationSize参数默认值为50,代表Hibernate每次从序列拉取一个基准值后,会在本地预分配50个连续ID,减少序列调用次数。- 你使用的PostgreSQL序列
some_sequence默认步长(increment by)为1,和Hibernate侧的allocationSize不匹配,Hibernate的ID生成逻辑校验到步长不一致时,会额外调用一次nextval拉取符合要求的基准值,因此出现两次序列查询。
调优方案
方案1:对齐配置参数(推荐,适配所有Hibernate版本)
只需要保证Hibernate侧的allocationSize和数据库序列的步长一致即可,有两种可选修改方式:
- 若写入量较大,建议修改数据库序列步长匹配默认
allocationSize,执行DDL:
alter sequence some_sequence increment by 50;
- 若写入量极小,也可以修改注解配置匹配默认序列步长:
@SequenceGenerator( name = "restricted_host_generator", sequenceName = "some_sequence", allocationSize = 1 )
注意:
allocationSize设为1会导致每次插入实体都调用一次nextval,高并发场景下性能损失较大,不推荐。
方案2:使用优化的序列生成器(适配Hibernate 5.4+版本)
Hibernate提供了pooled-lo序列优化器,是官方推荐的序列预缓存实现,相比默认的HiLo算法,生成的ID连续性更强,不会出现大量ID空洞,性能和HiLo一致,修改注解配置即可:
@SequenceGenerator( name = "restricted_host_generator", sequenceName = "some_sequence", allocationSize = 50, parameters = @org.hibernate.annotations.Parameter( name = "optimizer", value = "pooled-lo" ) )
使用该优化器同样需要保证
allocationSize和数据库序列步长一致。
修改配置后再次执行测试代码,仅会触发一次nextval调用,后续连续插入49条数据都不会再查询序列,直接使用本地缓存的ID池分配即可。
内容的提问来源于stack exchange,提问作者Semyon Kirekov
相关产品推荐
相关产品推荐

