it-swarm-id.com

Menyimpan vs menghitung nilai agregat

Apakah ada pedoman atau aturan praktis untuk menentukan kapan harus menyimpan nilai agregat dan kapan harus menghitungnya dengan cepat?

Misalnya, saya memiliki widget yang dapat dinilai pengguna (lihat skema di bawah). Setiap kali saya menampilkan widget, saya bisa menghitung nilai rata-rata pengguna dari tabel Ratings. Atau saya bisa menyimpan peringkat rata-rata di tabel Widget. Ini akan menyelamatkan saya dari keharusan menghitung peringkat setiap kali saya menampilkan widget, tetapi kemudian saya harus menghitung ulang peringkat rata-rata setiap kali pengguna memberi peringkat widget.

Ratings       Widgets
---------     -------
widget_id     widget_id
user_id       name              
rating        avg_rating  <--- The column in question
100
BenV

Tergantung. Pra-kalkulasi nilai agregat menempatkan beban yang lebih besar pada penulisan, menurunkannya membuat membaca lebih sulit

Jika Anda sering mengakses nilai turunan, pra-perhitungan adalah langkah de-normalisasi yang valid. Namun, dalam hal ini, saya sarankan menggunakan Tampilan Terwujud (tampilan, ditulis ke disk, ditautkan oleh pemicu ke tabel induk). Tampilan terwujud dirancang untuk menyimpan data yang sering ditanyakan tetapi membosankan, dan berguna untuk jumlah penulisan yang tinggi dan jumlah pembacaan yang rendah.

Dalam skenario penulisan tinggi, baca tinggi, pertimbangkan untuk memiliki tugas di latar belakang yang meniru efek dari pandangan terwujud, tetapi dalam waktu kurang dari waktu-nyata. Ini akan menyajikan rata-rata "cukup baik" sambil mempertahankan kinerja menulis dan membaca.

Dalam keadaan apa pun, jika Anda memperlakukan kolom turunan seperti kolom "normal": pastikan data yang disajikan dalam tampilan "Widget" ada di tempat lain dalam tabel, sehingga seluruh Tuple dapat diperoleh dengan proses apa pun yang Anda gunakan. Pertanyaan ini juga sangat spesifik untuk basis data (dan versi basis data), jadi saya merekomendasikan pengujian kinerja agregat (dengan indeks yang sesuai) terhadap kumpulan data berukuran normal dan tampilan terwujud.

60

Seberapa sering Anda perlu menghitung/menampilkan nilai relatif terhadap seberapa sering angka yang mendasarinya diubah/diperbarui.

Jadi, jika Anda memiliki situs web dengan 10k klik harian yang menampilkan nilai yang hanya akan berubah sekali dalam satu jam, saya akan menghitungnya ketika nilai yang mendasarinya berubah (bisa menjadi pemicu basis data, apa pun).

Jika Anda memiliki alat untuk melihat statistik, di mana statistik berubah dengan yang kedua, tetapi Anda hanya memiliki tiga orang yang memiliki akses, dan mereka hanya melihatnya beberapa kali sehari, saya akan lebih cenderung menghitung itu dengan cepat. (kecuali, butuh beberapa menit untuk menghitung bahwa memiliki data basi di tempat pertama bukanlah masalah besar ... dan bos saya memberitahu saya untuk hanya menghasilkan hal dari cron setiap jam, jadi dia tidak punya untuk menunggu ketika dia ingin melihatnya.)

11
Joe

Gunakan tabel StaleWidgets sebagai antrian dari widget "tidak valid" (akan dihitung ulang). Gunakan tugas utas lainnya (asinkron) yang dapat menghitung ulang nilai-nilai ini. Periode atau momen perhitungan ulang tergantung pada persyaratan sistem:

  • hanya membaca,
  • di akhir bulan,
  • untuk beberapa pengguna di awal hari
  • ...
4
garik

Saya akan menyarankan menghitung dengan cepat jika perhitungan tidak terlalu rumit dan dalam kasus di mana Anda memiliki perhitungan yang kompleks dan pembaruan sering tetapi tidak membaca frequnet daripada Anda dapat menyimpan data yang dihitung dan memiliki kolom tambahan (bool) yang akan menyimpan apakah perhitungan ulang diperlukan atau tidak . misalnya setel kolom ini menjadi true setiap kali perhitungan ulang harus dilakukan tetapi jangan lakukan perhitungan ulang dan ketika Anda melakukan perhitungan ulang atur kolom ini sebagai false (ini akan menunjukkan nilai yang dihitung adalah yang terbaru dan tidak basi).

Dengan cara ini Anda tidak perlu menghitung ulang setiap kali, Anda akan menghitung hanya ketika Anda harus membaca dan menghitung kembali nilai kolom itu benar. Dengan cara ini Anda akan menghemat banyak perhitungan ulang.

2
techExplorer

Untuk kasus tertentu ada solusi yang berbeda di mana Anda tidak perlu menambahkan semua peringkat dan membaginya dengan total untuk menemukan rata-rata. Alih-alih, Anda dapat memiliki bidang lain yang berisi total ulasan, sehingga setiap kali Anda menambahkan peringkat Anda menghitung rata-rata baru menggunakan (avg_rating × total + new_rating)/total, ini jauh lebih cepat daripada agregat dan mengurangi pembacaan disk karena Anda tidak harus mengakses semua nilai peringkat. Solusi serupa mungkin berlaku untuk kasus lain.

Kelemahan dari ini adalah bahwa itu bukan transaksi asam, sehingga Anda mungkin berakhir dengan peringkat yang sudah usang. Tetapi Anda masih bisa mengatasinya dengan menggunakan pemicu dalam database. Masalah lainnya adalah bahwa database tidak dinormalisasi lagi, tetapi jangan takut untuk mendenormalisasi data sebagai ganti kinerja.

2
Adrian Martinez