Katakanlah saya memiliki aplikasi basis data relasional dan objek "pengguna" dan objek "pesan". Sekarang saya ingin menunjukkan jumlah pesan yang belum dibaca kepada pengguna ini.
Apa cara terbaik untuk mengarsipkan ini? Apakah saya memperkenalkan bidang dalam pengguna dan menghitungnya jika pengguna menerima pesan dan mengurangi jumlah jika ia membacanya? Atau apakah saya menjalankan kueri setiap kali untuk menghitung jumlah pesan untuk pengguna yang ditandai sebagai belum dibaca?
Saya pikir pendekatan pertama lebih rumit dan rawan kesalahan, tetapi akan melakukan lebih baik daripada pendekatan kedua.
Bagaimana ini biasanya dilakukan atau apa pendekatan yang lebih baik?
Jawaban:
Pendekatan terbaik adalah mencobanya terlebih dahulu tanpa bidang tambahan, mengukur kinerja, dan jika ternyata terlalu lambat, Anda mencoba untuk mengoptimalkan. Ini bisa berarti untuk beralih ke pendekatan pertama Anda menggunakan bidang tambahan, tetapi Anda harus mempertimbangkan untuk menguji opsi lain juga, misalnya, menempatkan indeks tambahan pada bidang gabungan ("belum dibaca", "userID") pada pesan Anda.
sumber
Solusi buku teks sesuai dengan teori basis data adalah tidak memiliki nilai dalam database Anda yang bergantung pada nilai-nilai data lain, karena ini adalah dependensi transitif . Memiliki bidang yang merupakan nilai yang dihitung berdasarkan bidang lain merupakan pelanggaran normalisasi, karena itu mengarah pada informasi yang berlebihan.
Namun, terkadang apa yang dikatakan buku teks dan apa metode yang paling praktis dalam praktik berbeda. Menghitung jumlah pesan yang belum dibaca setiap tampilan halaman bisa menjadi operasi yang cukup mahal. Caching angka di
user
-tabel akan jauh lebih baik untuk kinerja. Biayanya adalah bahwa inkonsistensi mungkin ada dalam database: Mungkin ada kemungkinan pesan dihapus, ditambahkan atau dibaca tanpa mengingat untuk juga memperbarui konter yang belum dibaca.sumber
INSERT
atauDELETE
. (AtauUPDATE
, untuk menjelaskan perubahan pemilik pesan.). DBMS yang baik akan melakukan operasi dan menjalankan pemicu dalam transaksi yang sama, sehingga semua atau tidak sama sekali akan terjadi.Masalah potensial adalah kinerja dan Anda belum memiliki masalah kinerja. Ada banyak hal yang dapat Anda lakukan tergantung pada database pilihan untuk menangani ini dalam solusi # 1: pengindeksan, perangkat keras, caching, dll. Ini semua tergantung pada seberapa sering pengguna perlu mendapatkan jumlah pesan yang belum dibaca saat ini. Banyak dari pilihan ini tidak memerlukan pengkodean khusus di sisi aplikasi, sehingga Anda dapat menerapkannya dengan perubahan kode atau sangat sedikit. Membuatnya lebih mudah untuk tumbuh dengan aplikasi.
Setelah pengguna menghubungkan / masuk, mendapatkan hitungan dari basis data tidak terlalu buruk. Apakah aplikasi Anda akan terus memperbarui daftar pesan seperti email? Mendapatkan hitungan yang belum dibaca dari sini tidak memerlukan perjalanan lain ke database dan untuk mendapatkan pesan baru akan tetap melakukan perjalanan db.
Melakukan perjalanan ke db setiap kali pesan dibaca untuk menandai IsRead? bidang sudah cukup tanpa perhitungan ulang bidang lain.
Dengan solusi # 2 (menyimpan hitungan dalam bidang / pada disk), akankah Anda memerlukan rutin untuk membangun kembali secara berkala / menghitung ulang bidang ini saat ada masalah? Dan selalu ada masalah. Apakah Anda akan membungkus semua ini dalam suatu transaksi? Setiap kali seseorang mengirim pesan kepada orang lain, pesan itu bisa gagal karena tidak dapat memperbarui UnreadCount pengguna penerima karena kunci tabel Pengguna? Atau Anda akan membuat tabel terpisah untuk bidang ini?
sumber
Cara saya akan melakukannya adalah dengan mengeksekusi query setiap waktu, yaitu pendekatan kedua Anda. Pastikan Anda menambahkan indeks di tabel pesan di kolom yang berfungsi sebagai kunci asing ke tabel pengguna untuk meningkatkan kinerja kueri Anda.
Kemudian seperti yang dikatakan Doc, ukur kinerja pendekatan ini dan kemudian Anda akan dapat mengetahui apakah Anda perlu mengambil jalur yang berbeda.
sumber