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

Spring JPA-Hibernate:批量插入执行太多选择下一个(“序列”)

萧伟兆
2023-03-14

现在我正在尝试提高我的Web应用程序的性能,我使用Spring JPA 2.3.0-Hibernate 5.4.15。最终,Postgres 12并通过@Transaction管理事务。Web应用程序部署在aws beanstek上,同时运行多个实例,但数据库实例不可扩展。我使用bigSerial类型作为表的ID。

例如,我有一个学生表,ID是bigSerial和其他一些列。我在使用时遇到了一些问题

@GeneratedValue(策略=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 executeselect nextval30次,batch insert query 3次。

一些统计数据:

>

  • 保存(实体):
    • 插入到...:执行一次
    • 插入到...:执行n次

    如果使用GenerationType. SEQUENCE/GenerationType. AUTO

    • 保存(实体):
    • 选择nextval('students_id_seq'):执行n次
    • 插入到 :执行n次/批大小

    总之,如果使用GenerationType。自动或生成类型。序列带有allocationSize=1

    • 当插入一个实体时,应用程序执行查询的次数增加了100%(从一个插入查询只增加到2个查询:选择nextval,并插入查询)
    • 批量插入时,如果batch_size=10,应用程序增加10%以上

    我的问题是,是否无论如何都要批量插入但不执行许多select nextval查询?类似GenerationType。IDENTITY,不执行select nextval,只是批量插入,ID将在数据库中按顺序处理。

    当我使用GenerationType进行测试时。SEQUENCEallocationSize=1(GenerationType.AUTO),应用程序执行了太多的select nextval查询,我认为这比身份策略更糟糕。由于某些原因,我不想使用allocationSize,在运行insert query manual或迁移数据或其他情况下,可能会导致重复的主键错误。

    经过一些研究,我找到了一种获取序列值列表的方法:

    从generate_series(1,10)中选择nextval('students_id_seq')

    我们可以用entityList代替10。批量插入时,大小()或实体数在entityList中没有ID,只需获得足够的使用量,不要在ID之间创建太多间隙,但我不确定是否支持Hibernate,如果支持,请与我共享文档以供参考。

    谢谢你

    https://discourse.hibernate.org/t/batch-insert-execute-too-much-select-nextval-sequence/4232


共有1个答案

淳于涛
2023-03-14

您正在寻找的是用于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;
 类似资料:
  • 我需要在一个批处理中向一个表中插入多行。在DatabaseClient中,我找到了insert()语句,并使用了(Publisher objectToInsert)方法,该方法有多个对象作为参数。但它是否会将它们放入一批中?另一种可能的解决方案是连接。createBatch(),但它有一个drowback:我无法在那里传递我的实体对象,也无法从实体生成sql查询。 那么,可以在r2dbc中创建批插

  • 我正在尝试在数据库表中上传Excel表。我正在将excel行转换为Hibernate实体并尝试将其保存在数据库中。为了实现这一点,我面临着问题。很少有db约束,如唯一或复合键等,但用户可以上传任何表。所以如果一个网格行无法插入,那么我的要求是其他行应该继续。和事务应该被保存。 '在这里,如果单行失败,那么所有行都失败。我得到org.hibernate.AssertionFailure:null i

  • 本文向大家介绍如何执行批量插入?相关面试题,主要包含被问及如何执行批量插入?时的应答技巧和注意事项,需要的朋友参考一下 首先,创建一个简单的 insert 语句:   然后在 java 代码中像下面这样执行批处理插入:

  • 问题内容: Hibernate提供(至少)两个选项来解决N + 1查询问题。一个是将FetchMode设置为Subselect,这会生成一个带有IN子句的选择以及此IN子句中的子选择。另一个是指定BatchSize,它会生成一个带有包含父母ID的IN子句的选择。 两者都可以工作,但是我发现由于对父项的查询很复杂,Subselect选项经常遇到性能问题。另一方面,对于大的BatchSize(例如10

  • 我正在开发一个spring批处理应用程序(内存为2GB),尝试处理数据(在处理过程中使用select查询获取数据),并在postgres DB中插入大约100万条处理过的记录。我在这个项目中使用Spring Data JPA。但是Spring JPA在处理这些记录时消耗了太多内存

  • 问题内容: 我正在插入一条记录,我想使用插入的最后一条记录的ID。这是我尝试过的: 我收到错误消息: SQL语法错误;请查看与您的MySQL服务器版本相对应的手册,以在“ SELECT LAST_INSERT_ID()”附近使用正确的语法。谁能告诉我我的错误在哪里?谢谢! 问题答案: 签出mysql_insert_id() 在mysql_query()命令中执行INSERT语句后运行该函数时,其结