Menyimpan vs menghitung nilai agregat


96

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 Ratingstabel. Atau saya bisa menyimpan nilai rata-rata di atas Widgetmeja. Ini akan menyelamatkan saya dari keharusan menghitung peringkat setiap kali saya menampilkan widget, tapi 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

Jawaban:


58

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

Jika Anda sering mengakses nilai yang diturunkan, 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 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 tupel dapat diturunkan 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.


Saya menemukan diskusi ini sangat membantu mengenai pandangan terwujud. Ini disesuaikan dengan Oracle tetapi dapat dipahami secara umum. Bagi mereka seperti saya yang berasal dari latar belakang MySQL, tampilan MySQL berbeda dari tampilan Materialized, itu virtual dan tidak menyimpan ke disk (seperti yang dibicarakan dalam tautan yang saya berikan).
Siddhartha

terbalik! hendak mengajukan pertanyaan yang tepat, saya perlu menyimpan indikator seperti SMA, EMA, WMA, RSI dll dan mereka melibatkan perhitungan yang berat, saya sedang membuat tabel saat ini yang secara manual menyegarkan sejauh ini, indikator ini berubah 100% setiap saat dengan data baru masuk, apa strategi yang baik untuk mempertahankannya, saya tahu tampilan akan sepenuhnya merobek basis data jika semua orang mulai menanyakan pandangan ke kiri dan kanan
PirateApp

11

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.)


setiap 15 menit, 10 metrik yang berubah 100% dengan 1000 baris per metrik
PirateApp

1
@ PirateApp dan berapa kali dilihat di jendela rata-rata 15 menit? Apa yang juga bisa Anda lakukan adalah menghasilkannya berdasarkan permintaan pertama dalam jendela 15 menit dan kemudian menyimpannya untuk orang-orang yang terus-menerus memukul reload
Joe

itu akan muncul di situs web jadi saya berasumsi setidaknya 10.000 orang akan melihatnya sebagai permulaan, situs ini tidak langsung jadi tidak memiliki data aktual tentang perilaku pengguna
PirateApp

1
Masalahnya adalah berapa banyak permintaan relatif terhadap seberapa sering itu berubah. Jadi jika Anda melakukan pra-menghasilkan sesuatu yang akan dilihat 10.000 kali sebelum data yang mendasarinya berubah, maka ya, pra-hasilkan. Jika hanya dilihat sekali, atau kurang dari satu kali (karena data berubah begitu cepat, atau karena halaman jarang dilihat), maka Anda tidak melihatnya.
Joe

4

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
  • ...

1
Bagaimana mereka masuk ke antrian basi itu?
jcolebrand

2
@jcolebrand ..pada saat memasukkan / menghapus peringkat (tabel Peringkat) untuk beberapa widget. Saat ini nilai rata-rata di tabel Widget menjadi tidak valid, jadi kami harus memasukkan ke dalam tabel catatan StaleWidgets yang hanya memiliki satu kolom - widget_id. Gunakan pemicu atau simpanan tersimpan yang memasukkan catatan ke tabel Peringkat atau varian Anda tentu saja.
garik

2

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 . mis. set 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 hanya akan menghitung ketika Anda harus membaca dan menghitung kembali nilai kolom itu benar. Dengan cara ini Anda akan menghemat banyak perhitungan ulang.


2

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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.