我正在嘗試向我的 Spring Boot 專案添加批量更新。批處理似乎已激活,但是當我檢查休眠日志時,仍然有多個查詢。
hibernate.jdbc.batch_size=5
休眠統計
295647400 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
3693300 nanoseconds spent preparing 21 JDBC statements;
5752515000 nanoseconds spent executing 20 JDBC statements;
1275544900 nanoseconds spent executing 4 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
1287992700 nanoseconds spent executing 1 flushes (flushing a total of 19 entities and 0 collections);
735000 nanoseconds spent executing 2 partial-flushes (flushing a total of 1 entities and 1 collections)
休眠日志
2022-10-09 19:21:16,192 DEBUG org.hibernate.engine.jdbc.spi.SqlStatementLogger: insert into SYSTEM.SNAPSHOT (CREATED_ON, ENTITY_PROPER_NAME, ID) values (?, ?, ?)
2022-10-09 19:21:16,192 DEBUG org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl: Reusing batch statement
2022-10-09 19:21:16,192 DEBUG org.hibernate.engine.jdbc.spi.SqlStatementLogger: insert into SYSTEM.SNAPSHOT (CREATED_ON, ENTITY_PROPER_NAME, ID) values (?, ?, ?)
2022-10-09 19:21:16,192 DEBUG org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl: Reusing batch statement
2022-10-09 19:21:16,192 DEBUG org.hibernate.engine.jdbc.spi.SqlStatementLogger: insert into SYSTEM.SNAPSHOT (CREATED_ON, ENTITY_PROPER_NAME, ID) values (?, ?, ?)
2022-10-09 19:21:16,193 DEBUG org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl: Reusing batch statement
2022-10-09 19:21:16,193 DEBUG org.hibernate.engine.jdbc.spi.SqlStatementLogger: insert into SYSTEM.SNAPSHOT (CREATED_ON, ENTITY_PROPER_NAME, ID) values (?, ?, ?)
2022-10-09 19:21:16,193 DEBUG org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl: Reusing batch statement
2022-10-09 19:21:16,193 DEBUG org.hibernate.engine.jdbc.spi.SqlStatementLogger: insert into SYSTEM.SNAPSHOT (CREATED_ON, ENTITY_PROPER_NAME, ID) values (?, ?, ?)
2022-10-09 19:21:16,193 DEBUG org.jboss.logging.DelegatingBasicLogger: Executing batch size: 5
我期待 hibernate 為 Oracle 資料庫生成如下所示的陳述句。
INSERT ALL
INTO Snapshot ( created_on, entity_proper_name, id ) VALUES ( ?, ?, ? )
INTO Snapshot ( created_on, entity_proper_name, id ) VALUES ( ?, ?, ? )
INTO Snapshot ( created_on, entity_proper_name, id ) VALUES ( ?, ?, ? )
SELECT 1 FROM dual;
當我將執行的陳述句檢查到 Jprofiler 或直接檢查到 Oracle 時,它??與休眠日志中顯示的相同。如果單獨運行插入,執行計數也應相同。

Hibernate 批處理是否適用于 Oracle 資料庫?
代碼片段
Spring Boot v2.7.1
Spring v5.3.21
Java 17.0.3.1
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
應用程式.yml
spring:
datasource:
url: jdbc:oracle:thin:@localhost:1521/db
username: user
password: password
driver-class-name: oracle.jdbc.OracleDriver
jpa:
database-platform: org.hibernate.dialect.Oracle12cDialect
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
ddl-auto: update
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.Oracle12cDialect
format_sql: false
jdbc:
fetch_size: 100
batch_size: 5
order_updates: true
order_inserts: true
batch_versioned_data: true
generate_statistics: true
快照物體
@Entity
@Table(name = "SNAPSHOT", schema = "SYSTEM", catalog = "")
public class Snapshot {
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Id
@Column(name = "ID")
private long id;
@Basic
@Column(name = "CREATED_ON")
private String createdOn;
...
}
快照服務
@Transactional
public void execute() {
...
for (int i = 0; i < snapshots.size(); i ) {
snapshots.get(i).setFieldValue(fieldValue);
snapshots.get(i).setCreatedOn(createdOn);
}
snapshotRepository.saveAll(snapshots);
...
}
pom.xml
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc11</artifactId>
<version>21.7.0.0</version>
</dependency>
uj5u.com熱心網友回復:
我不希望 hibernate 使用特殊的多插入語法,這是特定于供應商的。它寧可使用所謂的(有時)陣列操作,它發送帶有值(行)陣列的引數化查詢,oracle jdbc 驅動程式確實支持。這是一篇隨機的 oracle 文章,提到了這些東西,但是所有主要的資料庫都有這種可能性,這里有一些使用它的jdbc 示例代碼(沒有休眠)。
您的所有日志也都如此。Jdbc 表示它為 20 次插入運行了 4 批,每批 5 行。任何加速都來自于網路往返次數的減少以及資料庫中每個批量更新只有一次查找或決議操作。Oracle 的 sql 引擎仍然會在所有相關的盛況和情況下每行執行 1 次插入,例如約束檢查和索引維護。我知道解決這個問題的唯一方法是使用直接路徑模式的 oracle 加載程式。
但是要驗證 oracle 是否真正使用批處理陳述句是一個問題,因為它具有資料傳輸功能。sql 引擎將再次運行單獨的陳述句。
對于相同的資料,至少應該看到大約 50% 的顯著速度提高,盡管這可能取決于插入的資料型別。與非批處理操作相比,此評估說明了 500%,但這并不足以證明。您可以在插入時為定義的行數引發資料庫錯誤,然后檢查引發的例外(應該是 some BatchUpdateException)和實際處理的行數。這可能足以證明批處理發生在客戶端。jdbc 代碼中的斷點也可能OraclePreparedStatement.sendBatch()是我猜的候選者。也許您可以除錯 oracle 可執行檔案。您必須使用不使用瘦客戶端的連接,就像您一樣(jdbc:oracle:thin...),但是 OCI 客戶端(oracle 呼叫介面),您要搜索的電話是OCIBindArrayOfStruct。對于資料庫服務器端,我真的不知道。也許可以通過嗅探 IP 流量來確定每 n 行的請求數。
就我而言,我將相同資料的加速作為足夠的證據,即發生了批處理。即使沒有,我所需要的只是加速。
uj5u.com熱心網友回復:
我相信這是因為Hibernate 提供的分配大小。
在您的物體類中,您可以嘗試更改 allocationSize 嗎?
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SNAPSHOT_SEQ")
@SequenceGenerator(name = "SNAPSHOT_SEQ", sequenceName = "SNAPSHOT_SEQ", allocationSize = 150)
@Column(name = "ID", nullable = false)
private Long id;
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/515520.html
上一篇:HibernateSearch-即使Elasticsearch集群關閉也啟動應用程式
下一篇:執行卡住:Hibernate OracleDBwithWallet:DriverManagerConnectionProviderImpl-HHH000115:Hibernate連接池大小:20(mi
