shopkeeper
tabel memiliki bidang berikut:
id (bigint),amount (numeric(19,2)),createddate (timestamp)
Katakanlah, saya memiliki tabel di atas. Saya ingin mendapatkan catatan untuk kemarin dan menghasilkan laporan dengan memiliki jumlah yang dicetak ke sen.
Salah satu caranya adalah dengan melakukan perhitungan dalam aplikasi java saya dan menjalankan kueri sederhana
Date previousDate ;// $1 calculate in application
Date todayDate;// $2 calculate in application
select amount where createddate between $1 and $2
dan kemudian mengulangi catatan dan mengonversi jumlah menjadi sen dalam aplikasi java saya dan menghasilkan laporan
Cara lain adalah seperti melakukan perhitungan dalam kueri sql itu sendiri:
select cast(amount * 100 as int) as "Cents"
from shopkeeper where createddate between date_trunc('day', now()) - interval '1 day' and date_trunc('day', now())
dan kemudian mengulangi catatan dan menghasilkan laporan
Dalam satu cara, semua pemrosesan saya dilakukan dalam aplikasi java dan permintaan sederhana diaktifkan. Dalam kasus lain, semua konversi dan perhitungan dilakukan dalam permintaan Sql.
Kasus penggunaan di atas hanyalah sebuah contoh, dalam skenario nyata sebuah tabel dapat memiliki banyak kolom yang memerlukan pemrosesan yang serupa.
Bisakah Anda memberi tahu saya pendekatan mana yang lebih baik dalam hal kinerja dan aspek lainnya dan mengapa?
sumber
Jawaban:
Itu tergantung pada banyak faktor - tetapi yang paling penting:
Seperti biasa, jika Anda melakukan membawa kembali data ke aplikasi-server, meminimalkan kolom dan baris akan untuk keuntungan Anda. Memastikan kueri disetel dan diindeks dengan tepat akan membantu skenario mana pun.
Perhatikan kembali catatan Anda:
Looping melalui catatan hampir selalu merupakan hal yang salah untuk dilakukan dalam sql - menulis operasi berbasis set lebih disukai.
Sebagai aturan umum , saya lebih memilih untuk menjaga pekerjaan database seminimal mungkin "simpan data ini, ambil data ini" - namun, selalu ada contoh skenario di mana kueri elegan di server dapat menghemat banyak bandwidth.
Juga pertimbangkan: jika ini mahal secara komputasi, dapatkah itu di-cache di suatu tempat?
Jika Anda menginginkan "yang lebih baik" yang akurat ; buat kode baik dan bandingkan (perhatikan bahwa draf pertama dari keduanya kemungkinan tidak 100% disetel). Tetapi faktor dalam penggunaan khas untuk itu: jika, pada kenyataannya, itu disebut 5 kali (secara terpisah) sekaligus, maka simulasikan bahwa: jangan membandingkan hanya satu "1 dari ini vs 1 dari mereka".
sumber
Biarkan saya menggunakan metafora: jika Anda ingin membeli kalung emas di Paris, tukang emas bisa duduk di Cape Town atau Paris, itu adalah masalah keterampilan dan selera. Tetapi Anda tidak akan pernah mengirim berton-ton bijih emas dari Afrika Selatan ke Prancis untuk itu. Bijih diproses di lokasi penambangan (atau setidaknya di area umum), hanya emas yang dikirim. Hal yang sama harus berlaku untuk aplikasi dan database.
Sejauh menyangkut PostgreSQL , Anda dapat melakukan hampir semua hal di server, cukup efisien. RDBMS unggul dalam pertanyaan kompleks. Untuk kebutuhan prosedural, Anda dapat memilih dari berbagai bahasa skrip sisi server : tcl, python, perl, dan banyak lagi. Namun, kebanyakan saya menggunakan PL / pgSQL .
Skenario kasus terburuk adalah berulang kali pergi ke server untuk setiap baris satu set yang lebih besar. (Itu akan seperti pengiriman satu ton bijih sekali.)
Baris kedua , jika Anda mengirim sejumlah permintaan, masing-masing bergantung pada yang sebelumnya, sementara semua itu bisa dilakukan dalam satu permintaan atau prosedur di server. (Itu seperti mengirim emas, dan masing-masing permata dengan kapal terpisah, secara berurutan.)
Bolak-balik antara aplikasi dan server itu mahal. Untuk server dan klien. Cobalah untuk mengurangi itu, dan Anda akan menang - ergo: gunakan prosedur sisi server dan / atau SQL canggih jika perlu.
Kami baru saja menyelesaikan sebuah proyek di mana kami mengemas hampir semua permintaan kompleks ke dalam fungsi Postgres. Aplikasi menyerahkan parameter dan mendapatkan set data yang dibutuhkan. Cepat, bersih, sederhana (untuk pengembang aplikasi), I / O dikurangi menjadi minimum ... kalung berkilau dengan jejak karbon rendah.
sumber
Dalam hal ini Anda mungkin sedikit lebih baik melakukan perhitungan dalam SQL karena mesin database cenderung memiliki rutinitas aritmatika desimal yang lebih efisien daripada Java.
Meskipun untuk perhitungan level baris secara umum tidak ada banyak perbedaan.
Di mana itu membuat perbedaan adalah:
sumber
Tidak ada hitam / putih sehubungan dengan bagian apa dari logika akses data yang harus dilakukan dalam SQL dan bagian apa yang harus dilakukan dalam aplikasi Anda. Saya suka kata - kata Mark Gravell , yang membedakannya
Kekuatan dan ekspresifitas SQL sangat diremehkan. Sejak diperkenalkannya fungsi jendela , banyak perhitungan berorientasi non-ketat dapat dilakukan dengan sangat mudah dan elegan dalam database.
Tiga aturan praktis harus selalu diikuti, terlepas dari keseluruhan arsitektur aplikasi:
Dalam pengalaman saya, dengan DBA yang layak dan beberapa pengetahuan yang layak tentang database yang layak Anda, Anda tidak akan mengalami keterbatasan CPU DBs Anda segera.
Beberapa bacaan lebih lanjut di mana hal-hal ini dijelaskan:
sumber
Secara umum melakukan hal-hal dalam SQL jika ada kemungkinan juga modul atau komponen lain dalam proyek yang sama atau lainnya perlu mendapatkan hasil tersebut. operasi atom yang dilakukan sisi server juga lebih baik karena Anda hanya perlu memanggil proc yang tersimpan dari alat manajemen db untuk mendapatkan nilai akhir tanpa proses lebih lanjut.
Dalam beberapa kasus ini tidak berlaku tetapi ketika itu masuk akal. juga secara umum kotak db memiliki perangkat keras dan kinerja terbaik.
sumber
Jika Anda menulis di atas ORM atau menulis aplikasi kasual berkinerja rendah, gunakan pola apa pun yang menyederhanakan aplikasi. Jika Anda menulis aplikasi berkinerja tinggi dan memikirkan skala, Anda akan menang dengan memindahkan pemrosesan ke data. Saya sangat menganjurkan untuk memindahkan pemrosesan ke data.
Mari kita pikirkan tentang ini dalam dua langkah: (1) transaksi OLTP (jumlah kecil catatan). (2) OLAP (pemindaian panjang banyak catatan).
Dalam kasus OLTP, jika Anda ingin cepat (10k - 100k transaksi per detik), Anda harus menghapus kait, kunci, dan pertikaian kunci mati dari database. Ini berarti bahwa Anda perlu menghilangkan warung panjang dalam transaksi: perjalanan pulang-pergi dari klien ke DB untuk memindahkan pemrosesan ke klien adalah salah satu kios yang sangat panjang. Anda tidak dapat memiliki transaksi lama (untuk membuat baca / perbarui atom) dan memiliki throughput yang sangat tinggi.
Re: penskalaan horizontal. Skala basis data modern secara horizontal. Sistem-sistem tersebut sudah menerapkan HA dan toleransi kesalahan. Manfaatkan itu dan cobalah untuk menyederhanakan ruang aplikasi Anda.
Mari kita lihat OLAP - dalam hal ini jelas bahwa menyeret kemungkinan terrabytes data kembali ke aplikasi adalah ide yang mengerikan. Sistem-sistem ini dibangun secara khusus untuk beroperasi dengan sangat efisien terhadap data kolom yang terkompresi dan disusun sebelumnya. Sistem OLAP modern juga skala secara horizontal dan memiliki perencana kueri canggih yang menyebarkan pekerjaan secara horizontal (secara internal memindahkan pemrosesan ke data).
sumber
Apakah akan melakukan perhitungan di ujung depan atau di backend sangat diputuskan jika kita dapat menentukan tujuan kita dalam implementasi bisnis. Pada saat kode java mungkin berkinerja lebih baik daripada kode sql baik ditulis dengan baik atau mungkin sebaliknya. Tapi tetap saja jika bingung Anda bisa mencoba menentukan terlebih dahulu -
Ada banyak aspek lain yang dapat Anda pikirkan sebelum Anda memutuskan di mana menempatkan kode. Satu persepsi benar-benar salah - Semuanya dapat dilakukan terbaik di Jawa (kode aplikasi) dan / atau semuanya terbaik dilakukan oleh db (kode sql).
sumber
Membentuk sudut pandang kinerja: Ini adalah operasi aritmatika yang sangat sederhana yang hampir pasti dapat dilakukan jauh lebih cepat daripada benar-benar mengambil data dari disk yang menjadi basis data. Juga, menghitung nilai-nilai di mana klausa cenderung sangat cepat pada setiap runtime. Singkatnya, bottleneck harus disk IO, bukan perhitungan nilai.
Sesuai keterbacaan, saya pikir jika Anda menggunakan ORM Anda harus melakukannya di lingkungan server aplikasi Anda, karena ORM akan memungkinkan Anda bekerja dengan data yang mendasarinya dengan sangat mudah, menggunakan operasi berbasis set. Jika Anda akan menulis SQL mentah, tidak ada yang salah dengan melakukan perhitungan di sana, SQL Anda juga akan terlihat sedikit lebih bagus dan lebih mudah dibaca jika diformat dengan benar.
sumber
Yang terpenting, "kinerja" tidak didefinisikan.
Yang paling penting bagi saya adalah waktu pengembang.
Tulis kueri SQL. Jika terlalu lambat atau DB menjadi hambatan, maka pertimbangkan kembali. Pada saat itu, Anda dapat membandingkan dua pendekatan dan membuat keputusan berdasarkan data nyata yang relevan dengan pengaturan Anda (perangkat keras dan tumpukan apa pun yang Anda gunakan).
sumber
Saya tidak percaya perbedaan kinerja dapat dipikirkan tanpa contoh dan tolok ukur tertentu, tetapi saya harus mengambil lagi:
Mana yang bisa Anda pertahankan lebih baik? Misalnya, Anda mungkin ingin mengalihkan front-end Anda dari Java ke Flash, atau HTML5, atau C ++, atau yang lainnya. Sejumlah besar program telah melalui perubahan seperti itu, atau bahkan ada dalam lebih dari satu bahasa untuk memulai, karena mereka perlu bekerja pada beberapa perangkat.
Bahkan jika Anda memiliki lapisan tengah yang tepat (dari contoh yang diberikan, sepertinya bukan itu masalahnya), lapisan itu mungkin berubah dan JBoss mungkin menjadi Ruby / Rails.
Di sisi lain, tidak mungkin bahwa Anda akan mengganti SQL-backend dengan sesuatu yang bukan DB relasional dengan SQL dan bahkan jika Anda melakukannya, Anda harus menulis ulang front-end dari awal, jadi intinya adalah dapat diperdebatkan.
Gagasan saya adalah jika Anda melakukan perhitungan dalam DB, akan jauh lebih mudah untuk menulis front-end kedua atau lapisan-menengah nanti, karena Anda tidak harus mengimplementasikan kembali semuanya. Namun dalam praktiknya, saya pikir "di mana saya bisa melakukan ini dengan kode yang orang akan pahami" adalah faktor yang paling penting.
sumber
Untuk menyederhanakan cara menjawab ini adalah dengan melihat load balancing. Anda ingin meletakkan beban di tempat yang memiliki kapasitas paling besar (jika masuk akal). Dalam kebanyakan sistem itu adalah server SQL yang dengan cepat menjadi hambatan sehingga jawaban yang mungkin adalah bahwa Anda tidak ingin SQL melakukan satu ons pekerjaan lebih dari yang seharusnya.
Juga di sebagian besar arsitektur itu adalah SQL server (s) yang membentuk inti dari sistem dan sistem luar yang bisa ditambahkan.
Tetapi matematika di atas sangat sepele sehingga kecuali Anda mendorong sistem Anda ke batas tempat terbaik untuk meletakkannya adalah di mana Anda ingin meletakkannya. Jika matematika tidak sepele seperti menghitung sin / cos / tan untuk mengatakan perhitungan jarak maka upaya mungkin menjadi non-sepele dan memerlukan perencanaan dan pengujian yang cermat.
sumber
Jawaban lain untuk pertanyaan ini menarik. Anehnya, tidak ada yang menjawab pertanyaan Anda. Anda bertanya-tanya:
Info lebih lanjut: Untuk pertanyaan pertama, Anda ingin memastikan bahwa menggabungkan pecahan bekerja tanpa kesalahan pembulatan. Saya pikir angka 19,2 masuk akal untuk uang dan dalam kasus kedua bilangan bulat itu OK. Menggunakan pelampung untuk uang salah karena alasan ini.
Untuk pertanyaan kedua, saya ingin memiliki kontrol penuh sebagai programmer tanggal berapa yang dianggap "sekarang". Sulit untuk menulis tes unit otomatis saat menggunakan fungsi seperti sekarang (). Juga, ketika Anda memiliki skrip transaksi yang lebih panjang, ada baiknya untuk menetapkan variabel sama dengan sekarang () dan menggunakan variabel sehingga semua logika menggunakan nilai yang sama persis.
sumber
Biarkan saya mengambil contoh nyata untuk menjawab pertanyaan ini
Saya perlu menghitung rata-rata bergerak tertimbang pada data ohlc saya, saya memiliki sekitar 134.000 lilin dengan simbol untuk masing-masing melakukannya
Mana yang lebih baik?
Persyaratan
Untuk memberi Anda dorongan, ini adalah versi Python untuk melakukan moving average tertimbang
WMA dilakukan melalui kode
WMA Melalui SQL
Percaya atau tidak, kueri berjalan lebih cepat daripada versi Pure Python dalam melakukan RATA-RATA BERGERAK BERAT !!! Saya selangkah demi selangkah menulis pertanyaan itu, jadi tunggu sebentar dan Anda akan baik-baik saja
Mempercepat
0,42141127300055814 detik Python
0,23801879299935536 detik SQL
Saya memiliki 134.000 catatan OHLC palsu di basis data saya dibagi di antara 1.000 saham sehingga itu adalah contoh di mana SQL dapat mengungguli server aplikasi Anda
sumber