簡體   English   中英

Spring JPA - Hibernate: 批量插入執行過多 select nextval ('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... :執行一次
    • saveAll(n 個實體)
      • insert into... :執行n次
  • 如果使用 GenerationType.SEQUENCE/ GenerationType.AUTO

    • 保存(實體):
      • select nextval ('students_id_seq') : 執行一次
      • insert into... :執行一次
    • 全部保存(n 個實體):
      • select nextval ('students_id_seq') : 執行n次
      • insert into... :執行 n/batch_size 次

總之,如果使用GenerationType.AUTOGenerationType.SEQUENCE with allocationSize = 1

  • 當插入一個實體時,應用程序增加 100% 次執行查詢(從一個插入查詢僅增加到 2 個查詢:select nextval,並插入查詢)
  • 批量插入時,如果 batch_size = 10,應用程序增加超過 10%

我的問題是,是否有批量插入但不執行許多select nextval查詢? 類似GenerationType.IDENTITY的東西,不執行select nextval ,只是批量插入,ID 將按數據庫中的順序處理。

當我使用GenerationType.SEQUENCEallocationSize=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 條記錄。 而我的目標是提高這樣做的耗時。 我會嘗試將案例總結如下:

  1. 該代碼沒有使用任何 persist() 或 save() 方法。 這些記錄是在@Transactionl 方法退出時保存的

  2. 我正在使用 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"

  3. 我修改了實體 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”值

  1. 此外,我還更改了序列“mappingentry_id_seq”以增加 40

進行這些更改后,時間從 55 秒減少到 20 秒,這是一個很大的影響

我唯一不明白的是,當我檢查序列生成的 id 列的值時,我沒有發現任何值差距。 每個 ID 值都超過前一個值 1,而不是 40。這就是我目前想要了解的

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM