Halo!
Pada artikel ini, saya akan secara singkat berbicara tentang pemrosesan batch pernyataan SQL (DML): INSERT, UPDATE, DELETE, sebagai salah satu cara untuk mencapai peningkatan kinerja.

Manfaat
Tidak seperti eksekusi berurutan dari setiap kueri SQL, pemrosesan batch memungkinkan untuk mengirim seluruh rangkaian kueri (paket) dalam satu panggilan, sehingga mengurangi jumlah koneksi jaringan yang diperlukan dan memungkinkan database untuk mengeksekusi sejumlah query secara paralel, yang secara signifikan dapat meningkatkan kecepatan eksekusi. Segera buat reservasi bahwa efek nyata dapat dilihat saat memasukkan, memperbarui atau menghapus data dalam jumlah besar ke dalam tabel database.
Tabel DB
Sebagai contoh, kita akan menggunakan tabel buku dengan bidang id dan judul.
1. JDBC - pemrosesan batch
Sebelum beralih ke contoh implementasi, perlu untuk menyoroti beberapa poin penting:
- JDBC , supportsBatchUpdates() DatabaseMetaData, , . true, .
- , setAutoCommit(false). , commit() rollback(). rollback() SQL .
- — , JDBC Statement, PreparedStatement CallableStatement, .
, Statement, PreparedStatement CallableStatement . , BATCH_SIZE. , . , , Hibernate 10 50.
, SQL INSERT. UPDATE, DELETE .
1.1. Statement
Statement book.
connection.setAutoCommit(false);
try (Statement stmt = connection.createStatement()) {
for (int i = 1; i <= SIZE; i++) {
stmt.addBatch("INSERT INTO book (title) VALUES ('" + "JDBC Insert Example: " + i + "')");
if (i % BATCH_SIZE == 0 || i == SIZE) {
try {
int[] result = stmt.executeBatch();
connection.commit();
} catch (BatchUpdateException ex) {
Log(ex);
connection.rollback();
}
}
}
}
:- C Statement;
- C void addBatch( String SQL );
- executeBatch(). executeBatch() .
Statement SQL INSERT, UPDATE, DELETE.
SQL , .
1.2. PreparedStatement
PreparedStatement book.
connection.setAutoCommit(false);
try (PreparedStatement pstmt = connection.prepareStatement("INSERT INTO book (title) VALUES (?)")) {
for (int i = 1; i <= SIZE; i++) {
pstmt.setString(1, "JDBC Insert Example: " + i);
pstmt.addBatch();
if (i % BATCH_SIZE == 0 || i == SIZE) {
try {
int[] result = pstmt.executeBatch();
connection.commit();
} catch (BatchUpdateException ex) {
Log(ex);
connection.rollback();
}
}
}
}
:- C PreparedStatement SQL ;
- , ;
- void addBatch();
- executeBatch().
3) 4) , Statement, — addBatch() .
SQL , , . , .
PreparedStatement SQL (INSERT, UPDATE, DELETE) Statement, - .
1.3. CallableStatement
CallableStatement .
, OUT INOUT.
CallableStatement book.
connection.setAutoCommit(false);
try (CallableStatement cstmt = connection.prepareCall("call insert_book(?)")) {
for (int i = 1; i <= SIZE; i++) {
cstmt.setString(1, "JDBC Insert Example: " + i);
cstmt.addBatch();
if (i % BATCH_SIZE == 0 || i == SIZE) {
try {
int[] result = cstmt.executeBatch();
connection.commit();
} catch (BatchUpdateException ex) {
Log(ex);
connection.rollback();
}
}
}
}
:- C CallableStatement ;
- , ;
- void addBatch();
- executeBatch().
, PreparedStatement.
, , .
- , .
CallableStatement , - .
1.4. BatchUpdateException
BatchUpdateException, . BatchUpdateException , SQL , - , ResultSet. BatchUpdateException ( getUpdateCounts()), , executeBatch. , SQL . , c (Statement.EXECUTE_FAILED) .
:
...
} catch (BatchUpdateException ex) {
int[] updateCount = ex.getUpdateCounts();
int count = 1;
for (int i : updateCount) {
if (i == Statement.EXECUTE_FAILED) {
System.out.println("Request " + count + ": Execute failed");
} else {
System.out.println("Request " + count + ": OK");
}
count++;
}
}
...
. , , , , . BatchUpdateException SQL , . .
2. Hibernate —
2.1.
, , hibernate.jdbc.batch_size Hibernate.cfg.xml . Hibernate SQL INSERT, UPDATE, DELETE JDBC . SQL JDBC hibernate.order_inserts, hibernate.order_updates true, Hibernate SQL . SQL , JDBC Hibernate addBatch() PreparedStatement, SQL .
Hibernate.cfg.xml
...
<property name="hibernate.jdbc.batch_size">50</property>
<property name="hibernate.order_inserts">true</property>
<property name="hibernate.order_updates">true</property>
...
2.2.
. , . , Hibernate , OutOfMemoryException. 2 :
- flush() clear() .
:
try (Session session = HibernateUtil.getSessionFactory().getCurrentSession()) {
Transaction transaction = session.getTransaction();
transaction.begin();
for (int i = 1; i <= SIZE; i++) {
session.persist(new Book("Hibernate Insert Example: " + i));
if (i % BATCH_SIZE == 0) {
session.flush();
session.clear();
}
}
transaction.commit();
}
- StatelessSession. StatelessSession . , , , (aliasing) . , Hibernate. Hibernate.
:
try (StatelessSession session = HibernateUtil.getSessionFactory().openStatelessSession()) {
Transaction transaction = session.getTransaction();
transaction.begin();
for (int i = 1; i <= SIZE; i++) {
session.persist(new Book("Hibernate Insert Example: " + i));
}
transaction.commit();
}
Eksekusi batch query SQL adalah salah satu cara terkenal untuk meningkatkan kinerja yang harus Anda perhatikan. Mengurangi jumlah koneksi jaringan ke database dan meningkatkan kecepatan eksekusi query adalah nilai tambah yang signifikan dalam penggunaan pemrosesan batch.
Contoh kode dapat ditemukan di GitHub .