Artikel ini menjelaskan metode pemrosesan batch hibernate dari data besar -besaran. Bagikan untuk referensi Anda, sebagai berikut:
Hibernate batch pemrosesan jumlah besar sebenarnya tidak diinginkan dari perspektif kinerja dan membuang banyak memori. Dari mekanismenya, Hibernate pertama -tama memeriksa data yang memenuhi kondisi, menempatkannya dalam memori, dan kemudian melakukan operasi. Kinerja sangat tidak memuaskan dalam penggunaan aktual. Dalam penggunaan aktual saya, data solusi optimisasi ketiga berikut adalah: 100.000 lembar data dimasukkan ke dalam database, yang membutuhkan waktu sekitar 30 menit. Haha, pingsan. (Saya memasukkan 1000.000 data dalam 10 menit (bidangnya relatif kecil))
Ada tiga cara untuk menghadapinya untuk menyelesaikan masalah kinerja:
1: Memotong API Hibernate dan secara langsung menggunakan JDBC API. Metode ini memiliki kinerja yang lebih baik. Ini juga yang tercepat.
2: Gunakan prosedur tersimpan.
3: Gunakan API Hibernate untuk melakukan pemrosesan batch reguler. Mungkin ada perubahan, dan perubahan akan berubah. Ketika kami menemukan jumlah tertentu, kami dapat menghapus data dalam waktu setelah menyelesaikan operasi, session.flush (); session.evict (set objek xx); Ini juga dapat menghemat beberapa kerugian kinerja. "Jumlah tertentu" ini perlu digunakan sebagai referensi kuantitatif berdasarkan kondisi aktual. Umumnya sekitar 30-60, tetapi efeknya masih tidak ideal.
1: Memotong API Hibernate dan melakukannya langsung melalui JDBC API. Metode ini memiliki kinerja yang lebih baik dan tercepat. (Contohnya adalah operasi pembaruan)
Transaksi tx = session.begintransaction (); // Perhatikan bahwa Anda menggunakan koneksi batas transaksi hibernate conn = session.connection (); PreparedStatement stmt = conn.preparedStatement ("Perbarui Pelanggan sebagai c set c.sarlary = c.sarlary+1 di mana c.sarlary> 1000"); stmt.excuteUpdate (); tx.commit (); // Perhatikan bahwa Anda menggunakan batas transaksi hibernate Dalam applet ini, menggunakan API yang secara langsung memanggil JDBC untuk mengakses database, yang sangat efisien. Hindari masalah kinerja yang disebabkan oleh hibernate kueri pertama dan memuat ke dalam memori, dan kemudian melakukan operasi.
2: Gunakan prosedur tersimpan. Namun, metode ini tidak disarankan untuk digunakan karena kenyamanan portabilitas dan penyebaran program. (Contohnya adalah operasi pembaruan)
Jika database yang mendasarinya (seperti Oracle) mendukung prosedur tersimpan, pembaruan batch juga dapat dilakukan melalui prosedur tersimpan. Prosedur tersimpan berjalan langsung di database, lebih cepat. Dalam database Oracle, prosedur tersimpan bernama BatchUpDateCustomer () dapat didefinisikan, kode tersebut adalah sebagai berikut:
Salinan kode adalah sebagai berikut: Buat atau ganti Prosedur BatchUpDateCustomer (P_AGE IN NUMBER) Saat Mulai Perbarui Pelanggan Set Usia = Usia+1 Di mana Usia> P_AGE; END;
Prosedur tersimpan di atas memiliki parameter P_AGE, yang mewakili usia klien. Aplikasi dapat memanggil prosedur tersimpan dengan cara berikut:
tx = session.begintransaction (); koneksi con = session.connection (); Prosedur String = "{Call BatchupDateCustomer (?)}"; callablestatement cstmt = con.prepareCall (prosedur); cstmt.setint (1, 0); // Atur parameter usia ke 0cstmt.executeUpdate (); tx.commit ();Seperti yang dapat dilihat dari program di atas, aplikasi juga harus memotong API hibernate dan secara langsung memanggil prosedur tersimpan melalui JDBC API.
3: Gunakan API Hibernate untuk melakukan pemrosesan batch reguler. Mungkin ada perubahan, dan perubahan akan berubah. Ketika kami menemukan jumlah tertentu, kami dapat menghapus data dalam waktu setelah menyelesaikan operasi, session.flush (); session.evict (set objek xx); Ini juga dapat menghemat beberapa kerugian kinerja. "Jumlah tertentu" ini perlu menjadi referensi kuantitatif berdasarkan kondisi aktual ...
(Contohnya adalah operasi penyelamatan)
Logika bisnis adalah: kami ingin memasukkan 10 0000 lembar data ke dalam database
tx = sesi.
Ini akan menjaga sistem dalam kisaran yang stabil ...
Selama proses pengembangan proyek, karena persyaratan proyek, kita sering perlu memasukkan data dalam jumlah besar ke dalam database. Ada puluhan ribu, puluhan ribu, puluhan juta, bahkan puluhan juta dari mereka. Jika Anda menggunakan Hibernate untuk memasukkan data tingkat besarnya ini, pengecualian dapat terjadi. Pengecualian umum adalah outofmemoryError (pengecualian overflow memori).
Pertama, mari kita tinjau secara singkat mekanisme operasi penyisipan hibernate. Hibernate perlu mempertahankan cache internalnya. Saat kami melakukan operasi insert, kami akan menempatkan semua objek untuk beroperasi di cache internal kami untuk manajemen.
Ketika datang ke cache Hibernate, Hibernate memiliki teori cache internal dan cache sekunder. Karena Hibernate memiliki mekanisme manajemen yang berbeda untuk kedua cache ini, kita dapat mengonfigurasi ukurannya dalam kaitannya dengan cache sekunder, sedangkan untuk cache internal, Hibernate mengadopsi sikap "streaming tali", dan tidak ada batasan kapasitasnya. Sekarang inti dari masalah ditemukan. Ketika kami memasukkan data besar -besaran, begitu banyak objek yang akan dimasukkan dalam cache internal (cache internal di -cache dalam memori), sehingga memori sistem Anda akan dimakan sedikit demi sedikit. Jika sistem akhirnya "digoreng", itu masuk akal.
Mari kita pikirkan tentang bagaimana mengatasi masalah ini dengan lebih baik? Beberapa kondisi pengembangan harus ditangani menggunakan hibernate, dan tentu saja beberapa proyek lebih fleksibel dan Anda dapat menemukan metode lain.
Di sini saya merekomendasikan dua metode:
(1): Mengoptimalkan Hibernate, dan gunakan metode penyisipan tersegmentasi untuk menghapus cache pada waktunya pada program.
(2): Bypass API Hibernate dan lakukan pemasangan batch langsung melalui JDBC API. Metode ini memiliki kinerja terbaik dan tercepat.
Untuk metode 1 di atas, ide dasarnya adalah: mengoptimalkan hibernate, atur parameter hibernate.jdbc.batch_size dalam file konfigurasi untuk menentukan jumlah SQL yang dikirimkan setiap kali; Program ini menggunakan metode membersihkan cache dalam waktu dalam penyisipan tersegmentasi (sesi mengimplementasikan penulisan-belakang yang tidak sinkron, yang memungkinkan hibernasi untuk secara eksplisit menulis operasi), yaitu, membersihkannya dari cache internal pada waktunya setelah memasukkan sejumlah data, dan membebaskan memori yang ditempati.
Untuk mengatur parameter hibernate.jdbc.batch_size, Anda dapat merujuk ke konfigurasi berikut.
<Hibernate-konfigurasi> <Session-factory> ... <name properti = "hibernate.jdbc.batch_size"> 50 </prop Property> ... <sesi-Factory> <hibernate-konfigurasi>>
Alasan untuk mengkonfigurasi parameter hibernate.jdbc.batch_size adalah untuk membaca database sesedikit mungkin. Semakin besar nilai parameter hibernate.jdbc.batch_size, semakin sedikit waktu Anda membaca database, dan semakin cepat kecepatannya. Dari konfigurasi di atas, dapat dilihat bahwa hibernasi menunggu sampai program menumpuk 50 sql sebelum mengirimkannya dalam batch.
Penulis juga berpikir bahwa nilai parameter hibernate.jdbc.batch_size mungkin tidak ditetapkan sebesar mungkin, dan masih harus dibahas dari perspektif kinerja. Ini membutuhkan pertimbangan situasi aktual dan menetapkannya sesuai kebutuhan. Umumnya, pengaturan 30 atau 50 dapat memenuhi kebutuhan.
Dalam hal implementasi program, penulis mengambil penyisipan 10.000 lembar data sebagai contoh,
Sesi sesi = hibernateutil.currentsession (); transatcion tx = session.begintransaction (); for (int i = 0; i <10000; i ++) {student st = baru siswa (); st.setname ("feifei"); session.save (st); if (i%50 == 0) // Gunakan setiap 50); Sesi. // Tetap sinkron dengan Database Data Session.Clear (); // Bersihkan semua data di -cache secara internal dan lepaskan memori yang ditempati dalam waktu}} tx.Commit (); ...Di bawah skala data tertentu, pendekatan ini dapat mempertahankan sumber daya memori sistem dalam kisaran yang relatif stabil.
Catatan: cache tingkat kedua yang disebutkan sebelumnya diperlukan bagi saya untuk menyebutkannya di sini. Jika cache sekunder diaktifkan, untuk mempertahankan cache sekunder, hibernate akan mengisi daya data yang sesuai ke cache sekunder saat kami memasukkan, memperbarui, dan menghapus operasi. Akan ada kerugian besar dalam kinerja, jadi penulis merekomendasikan untuk menonaktifkan cache Level 2 dalam pemrosesan batch.
Untuk Metode 2, pemrosesan batch JDBC tradisional digunakan dan JDBC API digunakan untuk memprosesnya.
Silakan merujuk ke pemrosesan Batch Java dan SQL Ekseksi Diri.
Melihat kode di atas, apakah Anda selalu merasa bahwa ada sesuatu yang tidak pantas? Ya, tidakkah Anda menyadarinya! Ini masih merupakan pemrograman tradisional JDBC, tanpa rasa hibernasi.
Kode di atas dapat dimodifikasi dengan yang berikut:
Transaksi tx = session.begintransaction (); // Gunakan koneksi pemrosesan transaksi hibernate conn = session.connection (); Persiapan stmt = conn.prepareStatement ("masukkan ke dalam nilai t_student (name) (?)"); untuk (int j = 0; j ++; j <200) {untuk (int i = 0; i ++; j <50) {stmt.setstring (1, "feifei");}} stmt.executeupdate (); tx.commit (); // Gunakan batas pemrosesan transaksi hibernate ...Perubahan ini akan memiliki rasa hibernasi. Setelah pengujian, penulis menggunakan API JDBC untuk pemrosesan batch, yang hampir 10 kali lebih tinggi dalam kinerja daripada menggunakan Hibernate API. Ini tidak diragukan lagi kinerja dominan JDBC.
Dalam pembaruan batch dan penghapusan Hibernate2, untuk operasi pembaruan batch, Hibernate menemukan data yang memenuhi persyaratan dan kemudian melakukan operasi pembaruan. Hal yang sama berlaku untuk penghapusan batch. Pertama temukan data yang memenuhi persyaratan, dan kemudian lakukan operasi penghapusan.
Ini memiliki dua kerugian besar:
(1): Mengambil banyak memori.
(2): Saat memproses data besar -besaran, menjalankan pernyataan pembaruan/hapus adalah jumlah yang sangat besar, dan pernyataan pembaruan/hapus hanya dapat mengoperasikan satu objek. Dapat dibayangkan bahwa kinerja database rendah jika sering dioperasikan.
Setelah Hibernate3 dirilis, pembaruan/hapus massal diperkenalkan untuk operasi pembaruan/hapus batch. Prinsipnya adalah untuk menyelesaikan operasi pembaruan/menghapus batch melalui pernyataan HQL, yang sangat mirip dengan operasi pembaruan/penghapusan batch JDBC. Dalam hal kinerja, ada peningkatan besar dibandingkan pembaruan batch/penghapusan Hibernate2.
Transaksi tx = session.beginsession (); string hql = "hapus siswa"; kueri kueri = session.createqueery (hql); int size = query.executeUpdate (); tx.commit (); ...
Konsol hanya menghasilkan satu pernyataan hibernate: hapus dari t_student. Eksekusi pernyataan kurang, dan kinerjanya hampir sama dengan menggunakan JDBC. Ini adalah cara yang baik untuk meningkatkan kinerja. Tentu saja, untuk memiliki kinerja yang lebih baik, penulis merekomendasikan agar pembaruan batch dan operasi penghapusan masih menggunakan JDBC. Metode dan titik pengetahuan dasar pada dasarnya sama dengan metode penyisipan batch di atas 2, jadi saya tidak akan menggambarkannya secara berlebihan di sini.
Di sini saya memberikan metode lain, yaitu untuk mempertimbangkan meningkatkan kinerja dari sisi basis data dan panggilan prosedur tersimpan di sisi program hibernate. Prosedur tersimpan berjalan di sisi basis data, lebih cepat. Mengambil pembaruan batch sebagai contoh, kode referensi diberikan.
Pertama, buat prosedur tersimpan bernama BatchUpdatestudent di sisi database:
Buat atau ganti produksi BatchupDatestudent (A dalam angka) Asbeginupdate Siswa set Usia = Usia+1 Di mana Usia> A; Akhir;
Kode panggilan adalah sebagai berikut:
Transaksi tx = session.beginsession (); koneksi conn = session.connection (); string pd = "... {call batchupDatestudent (?)}"; Callablestatement cstmt = conn.prepareCall (PD); cstmt.setint (1, 20); // atur parameter usia ke 20tx.commit ();Mengamati kode di atas, itu juga memotong API hibernate dan menggunakan JDBC API untuk memanggil prosedur tersimpan, dan menggunakan batas transaksi Hibernate. Prosedur tersimpan tidak diragukan lagi merupakan cara yang baik untuk meningkatkan kinerja pemrosesan batch. Mereka berjalan langsung dengan sisi basis data, dan sampai batas tertentu mentransfer tekanan pemrosesan batch ke database.
Nota bene
Artikel ini membahas operasi pemrosesan batch Hibernate, dan titik awalnya adalah mempertimbangkan untuk meningkatkan kinerja, dan hanya memberikan aspek kecil untuk meningkatkan kinerja.
Tidak peduli metode apa yang diadopsi, itu harus dipertimbangkan berdasarkan kondisi aktual. Memberikan pengguna sistem yang efisien dan stabil yang memenuhi kebutuhan mereka adalah prioritas utama.
Saya harap artikel ini akan membantu pemrograman hibernate semua orang.