Haruskah Anda meninggalkan kerangka kerja ORM ketika Anda perlu menerapkan operasi massal?

15

Inilah situasi umum:

  • Anda perlu menerapkan operasi massal dalam aplikasi yang menggunakan kerangka kerja ORM.
  • Setelah lulus pertama, Anda telah melihat masalah kinerja yang signifikan.

Inilah pertanyaan saya:

  • Dalam situasi ini, haruskah Anda mendukung solusi yang mencakup SQL mentah?
  • Atau ada pola desain terkenal yang dapat membantu Anda mengurangi masalah yang umumnya terkait dengan operasi massal dengan kerangka kerja ORM?

EDIT:

  • Saya tidak bertanya apakah Anda harus menghapus kerangka kerja ORM dari seluruh aplikasi.
  • Saya bertanya: Haruskah Anda melupakan kerangka kerja ORM untuk aplikasi kecil ini?
Jim G.
sumber
Saya tidak tahu apakah Anda harus melakukan sesuatu, tetapi apakah Anda sudah mencoba menumpuk operasi massal Anda?
ChrisAnnODell

Jawaban:

13

ORM tidak dimaksudkan untuk sepenuhnya mengambil alih akses ke basis data Anda. Gunakan untuk 80% kode yang CRUD, hal-hal yang terlalu membosankan untuk ditulis sendiri. Gunakan prosedur tersimpan, SQL dinamis, atau apa pun yang Anda inginkan untuk sisa 20% yang perlu dioptimalkan dengan cermat.

Robert Harvey
sumber
4
Itu akan berhasil jika abstraksi basis data bukan salah satu alasan utama mengapa Anda memutuskan untuk menggunakan ORM.
@ Pierre303, saya kesulitan memahami komentar Anda. Apa maksudmu?
Mark Canlas
@ MarkCanlas: Saya pikir maksudnya "mengabstraksi database," dalam arti bahwa Anda dapat mengubah database (mis. Pergi dari SQL Server ke MySQL) jika Anda ingin melakukannya. Dalam praktiknya, use case ini jarang terjadi.
Robert Harvey
1
Anda masih dapat membuat abstraksi. Sebagian besar ORM yang benar-benar mendukung banyak penyedia / dialek memiliki dukungan untuk kode khusus penyedia / dialek. Anda dapat menerapkan operasi sebagai penyisipan massal / pengikatan array / TVP / apa pun untuk database tertentu dan membiarkannya kembali menjadi lambat demi lambat untuk penyedia yang tidak didukung seperti SQLite. Paling buruk Anda dapat membagi fungsionalitas yang mungkin massal ke antarmuka / kelas yang terpisah dan sub dalam implementasi yang berbeda berdasarkan parameter build atau config.
Aaronaught
Ya, dialek khusus dapat membantu, juga kode khusus untuk masalah tertentu. Namun agar ini dapat bertahan pada sudut pandang keuangan, ini harus dibatasi seminimal mungkin. Kustomisasi kami melalui fungsi khusus (dialek) mewakili kurang dari 0,1% dari total basis kode akses data. Saya akan benar-benar khawatir jika lebih dari itu.
7

Saya menggunakan ORM (nHibernate) dalam aplikasi yang membutuhkan kinerja tinggi dan menangani miliaran catatan. Seiring waktu kami memperhatikan bahwa sebagian besar masalah kinerja yang signifikan terkait dengan cara kami sendiri menggunakan ORM daripada karena ORM saja.

ORM seharusnya tidak menggantikan pengetahuan database wajib Anda. Ini adalah alat yang Anda gunakan untuk mendapatkan lebih banyak produktivitas dan fleksibilitas dalam kode Anda, tetapi Anda harus mengetahui proses yang mendasarinya untuk mengoptimalkan kinerja Anda.

Anda tidak menentukan ORM tertentu, jadi inilah hal-hal yang kami lakukan untuk meningkatkan kinerja:

  • Kami menggunakan profiler ORM. (kami menggunakan nhprof)
  • Kami menggunakan profiler basis data. (kami menggunakan SQL Server Profiler)
  • Kami membaca sebanyak mungkin artikel tentang masalah ini. (Banyak tersedia untuk nHibernate di samping seluruh bab tentang subjek dalam dokumentasi)
  • Kami membeli buku-buku tertentu tentang kinerja & skalabilitas.
  • Kami menciptakan sistem benchmark untuk menguji optimisasi kami sendiri.
  • dan yang lebih penting, kami dapat menguji kode kami dengan pelanggan di kehidupan nyata dengan data yang sangat besar. Hal terakhir itu sendiri membantu kami menemukan sebagian besar masalah dalam aplikasi kami.
Dan McGrath
sumber
1

Kami berhasil melakukannya dengan Entity Framework, tetapi aplikasi kami melakukan banyak operasi gaya batch (kami akan menulis sejumlah besar catatan ke tabel individu), jadi itu sangat cocok. Saya pasti akan melihat apakah mungkin untuk mempertahankan kerangka ORM jika memungkinkan, hanya untuk mengurangi jumlah kode tujuan khusus di aplikasi Anda. Apakah mungkin untuk menulis buffer, kemudian menjalankannya sebagai grup? Anda kehilangan semantik transaksi, tetapi jika Anda pergi dengan operasi massal saya menganggap Anda sudah setuju dengan itu.

TMN
sumber
1

ORM tidak melakukan sesuatu yang ajaib. Mereka menerjemahkan metode akses objek ke dalam SQL. Pernyataan SQL yang mereka jalankan tidak selalu lebih lambat dari SQL yang Anda tulis secara manual. Karena itu, ada beberapa masalah yang mungkin Anda temui:

  1. Transaksi: Satu operasi besar besar hampir selalu lebih cepat daripada banyak transaksi kecil yang bersama-sama mencapai hal yang sama. Oleh karena itu, jika panggilan metode ORM Anda menggunakan transaksi berbutir halus (metode gaya catatan aktif dalam entitas Spring Roo misalnya dijelaskan dengan @Transaksional secara default), operasi massal akan lambat. Jika itu yang terjadi dalam aplikasi Anda, Anda harus melihat logika transaksi Anda.
  2. Caching: Di Hibernate, cache tingkat pertama memungkinkan manajer entitas Anda untuk menghindari perjalanan buntu yang tidak perlu ke database. Hal yang baik secara umum, tetapi buruk untuk sisipan massal, yang menyebabkan penyumbatan cache yang tidak perlu, yang mengakibatkan penurunan kinerja aplikasi. Jika itu masalah Anda, Anda harus melihat pola Batching yang disarankan di atas oleh ChrisAnnODell. Kami menggunakannya di importir kami dan mempercepat banyak memasukkan massal.

Tidak ada yang salah dengan menggunakan SQL asli untuk meningkatkan kinerja. Tapi pertama-tama pastikan Anda mengerti apa yang memperlambat Anda.

wallenborn
sumber
Untuk menghindari cache, gunakan StatelessSession. Selain itu, hindari ID kenaikan otomatis. HiLo atau Guid harus digunakan sebagai gantinya.
1

Lewati ORM. Tidak hanya itu tetapi memotong sql "biasa" juga. Gunakan utilitas massal database Anda untuk menyisipkan set data yang sangat besar ke tabel pementasan. Kemudian gunakan sql untuk melakukan aktivitas pementasan Anda.

ORM "rasa-of-the-blog" Anda mungkin tidak berfungsi untuk semua situasi.

Tuan Tydus
sumber
Benar, alat back-end semacam ini sulit dipelajari, tetapi setelah sekitar 3 atau 4 kali, Anda akan menjadi ahli dan dapat melakukan hal-hal lebih cepat dan kadang-kadang hal-hal yang tidak dapat dilakukan dengan cara lain. Ini seperti perbedaan antara sekop dan buldoser. Saya telah menulis alat yang dikendalikan skrip untuk berbagai platform untuk membaca file input teks dan memperbarui data dengan operasi tingkat rendah. Menulis alat semacam itu juga dapat membuat hidup Anda lebih mudah (atau setidaknya lebih menarik). Hal-hal seperti ini dapat digunakan untuk mengubah data kustomisasi pada instalasi klien selama pembaruan perangkat lunak.
0

Berada dalam situasi itu. Terkadang Anda harus melakukannya.

Beberapa ORM memungkinkan pengembang untuk melewatkan model objek, dan langsung ke lapisan database.

Ada juga ORM, yang menggunakan operasi massal, dienkapsulasi, sebagai Object Oriented.

umlcat
sumber
0

Seperti disebutkan oleh umlcat , ada beberapa ORM yang memungkinkan Anda menggunakan operasi massal.

Bahkan lebih baik, banyak ORM dapat dikembangkan, jadi Anda bisa menulis metode Anda sendiri untuk menjalankan operasi massal, jika belum didukung. Jika operasi massal dalam aplikasi Anda adalah sesuatu yang Anda dapat faktor keluar, saya akan menambahkannya sebagai lapisan pada ORM (untuk melakukan itu, Anda mungkin perlu menulis SQL mentah), tetapi kemudian dalam aplikasi, gunakan ORM metode yang telah Anda terapkan.

Ini juga membuat pengujian dan debugging unit lebih mudah. Setelah Anda memiliki cakupan pengujian yang baik untuk metode ORM Anda, Anda bebas untuk menggunakannya di aplikasi Anda. Kalau tidak, debugging SQL mentah (terutama yang besar dengan transaksi dan banyak GABUNG) bisa menyebalkan.

Sekali waktu saya butuh hampir satu hari untuk menemukan bug di panggilan SQL mentah yang hampir 100 LOC, dan bug itu hanya satu karakter! Sejak itu, saya mencoba menghindari SQL mentah di dalam aplikasi, dan memiliki semua prosedur SQL yang diuji unit secara terpisah.

Attila O.
sumber
0

Yah tidak ada pola desain yang saya sadari. Dugaan saya adalah bahwa Anda membuat keputusan untuk ORM karena suatu alasan, jadi meninggalkan ORM kemungkinan bukan yang Anda inginkan. Namun, dalam kasus ini saya pikir ada ruang untuk menggabungkan kedua solusi. Tidak ada yang salah dengan itu, selama Anda melakukannya dengan hati-hati dan mendokumentasikan mengapa Anda menyimpang dari penggunaan standar ORM dalam perangkat lunak Anda. Selain itu, beberapa kerangka kerja ORM memiliki beberapa fasilitas untuk melakukan operasi massal. Saya tahu nHibernate (ORM untuk .NET framework) telah memanggil StatelessSessions, yang memiliki overhead yang jauh lebih sedikit, tetapi ini mungkin masih tidak memberi Anda peningkatan kinerja yang Anda cari. Dalam hal ini, cukup gunakan SQL mentah.

Pieter
sumber