![](/img/trans.png)
[英]Hibernate doesn't insert child entities: Hibernate: select nextval ('hibernate_sequence')
[英]Spring JPA - Hibernate: Batch insert execute too much select nextval (‘sequence’)
现在我正在尝试提高我的 web 应用程序的性能,我使用 spring JPA 2.3.0- Hibernate 5.4.15.Final,Postgres 12 并通过@Transaction 管理事务。 web app部署在aws beanstalk上,同时运行多个实例,但数据库实例不可扩展。 我使用 bigSerial 类型作为表的 ID。
例如,我有一个 STUDENTS 表,ID 是 bigSerial 和一些其他列。 我在使用时遇到问题
@GeneratedValue(strategy = GenerationType.IDENTITY)
, Hibernate 保存实体列表时无法批量插入。 我尝试使用
@GeneratedValue(strategy = GenerationType.AUTO, generator = "students_id_seq")
@SequenceGenerator(name = "students_id_seq", sequenceName = "students_id_seq")
hibernate.id.new_generator_mappings=false
hibernate.jdbc.batch_size=10
hibernate.order_inserts=true
hibernate.order_updates=true
hibernate.batch_versioned_data=true
好像Hibernate可以批量插入,问题是Hibernate多次执行select nextval ('students_id_seq')
。 如果实体列表有30条,Hibernate执行30次select nextval
,3次批量插入查询。
一些统计数据:
如果使用 GenerationType.IDENTITY
insert into...
:执行一次insert into...
:执行n次如果使用 GenerationType.SEQUENCE/ GenerationType.AUTO
select nextval ('students_id_seq')
: 执行一次insert into...
:执行一次select nextval ('students_id_seq')
: 执行n次insert into...
:执行 n/batch_size 次总之,如果使用GenerationType.AUTO
或GenerationType.SEQUENCE
with allocationSize = 1
:
我的问题是,是否有批量插入但不执行许多select nextval
查询? 类似GenerationType.IDENTITY
的东西,不执行select nextval
,只是批量插入,ID 将按数据库中的顺序处理。
当我使用GenerationType.SEQUENCE
和allocationSize=1
(GenerationType.AUTO)
进行测试时,应用程序执行了过多的select nextval
查询,我认为它甚至比 IDENTITY 策略更糟糕。 而且由于某些原因,我不想使用allocationSize
,它可能会导致在运行 insert query manual 或 migrate data 时或其他一些情况下出现重复的主键错误。
经过一些研究,我找到了一种获取序列值列表的方法:
select nextval ('students_id_seq') from generate_series(1,10);
我们可以用entityList.size()代替10或者实体数量在批量插入时entityList中没有ID,够用就好了,不要在ID之间造成太大的差距,但我不确定是否或不支持 Hibernate,如果支持,请将文档分享给我以供参考。
谢谢
https://discourse.hibernate.org/t/batch-insert-execute-too-much-select-nextval-sequence/4232
您正在寻找的是用于 id 生成的HiLo 算法。
对于从序列生成的每个 id,它会在客户端生成多个 id,而无需访问数据库。
您在实体上将其配置为:
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hilo_sequence_generator")
@GenericGenerator(
name = "hilo_sequence_generator",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
@Parameter(name = "sequence_name", value = "hilo_seqeunce"),
@Parameter(name = "initial_value", value = "1"),
@Parameter(name = "increment_size", value = "3"),
@Parameter(name = "optimizer", value = "hilo")
})
@Id
private Long id;
我会说我在这一点上有一些经验。 我正在插入超过 128,000 条记录。 而我的目标是提高这样做的耗时。 我会尝试将案例总结如下:
该代码没有使用任何 persist() 或 save() 方法。 这些记录是在@Transactionl 方法退出时保存的
我正在使用 hibernate 下面的批量插入是配置 map 中的设置
spring.jpa.properties.hibernate.jdbc.batch_size: "40" spring.jpa.properties.hibernate.order_inserts: "true" spring.jpa.properties.hibernate.order_updates: "true" spring.main.allow-bean-definition-overriding: "true"
我修改了实体 ID 配置中的分配大小,如下所示:
@ID
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator ="mappingentry_sql_generator")
@SequenceGenerator(name = "mappingentry_sql_generator", sequenceName ="mappingentry_id_seq", allocationSize = 40)
private Long id;
注意:我将序列生成器中的“allocationSize”设置为等于设置中的“batch_size”值
进行这些更改后,时间从 55 秒减少到 20 秒,这是一个很大的影响
我唯一不明白的是,当我检查序列生成的 id 列的值时,我没有发现任何值差距。 每个 ID 值都超过前一个值 1,而不是 40。这就是我目前想要了解的
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.