Kami sedang mengembangkan platform untuk kartu prabayar, yang pada dasarnya menyimpan data tentang kartu dan saldo, pembayaran, dll.
Hingga kini kami memiliki entitas Kartu yang memiliki koleksi entitas Akun, dan setiap Akun memiliki Jumlah, yang diperbarui di setiap Setoran / Penarikan.
Sekarang ada perdebatan di tim; seseorang telah memberi tahu kami bahwa ini melanggar 12 Aturan Codd dan memperbarui nilainya pada setiap pembayaran adalah masalah.
Apakah ini benar-benar masalah?
Jika ya, Bagaimana kita bisa memperbaikinya?
database-design
rdbms
Mithir
sumber
sumber
Jawaban:
Ya, itu non-normalisasi, tetapi kadang-kadang desain non-normalisasi menang karena alasan kinerja.
Namun, saya mungkin akan mendekatinya sedikit berbeda, untuk alasan keamanan. (Penafian: Saat ini saya tidak, saya juga tidak pernah bekerja di sektor keuangan. Saya hanya membuang ini di sana.)
Siapkan tabel untuk saldo yang diposting pada kartu. Ini akan memiliki baris yang dimasukkan untuk setiap akun, menunjukkan saldo yang diposting pada penutupan setiap periode (hari, minggu, bulan, atau apa pun yang sesuai). Indeks tabel ini berdasarkan nomor dan tanggal akun.
Gunakan tabel lain untuk menahan transaksi yang tertunda, yang dimasukkan dengan cepat. Pada penutupan setiap periode, jalankan rutin yang menambahkan transaksi yang belum diposkan ke saldo akhir akun untuk menghitung saldo baru. Entah menandai transaksi yang tertunda sebagai diposting, atau lihat tanggal untuk menentukan apa yang masih tertunda.
Dengan cara ini, Anda dapat menghitung saldo kartu sesuai permintaan, tanpa harus menjumlahkan semua riwayat akun, dan dengan menempatkan perhitungan ulang saldo dalam rutin posting khusus, Anda dapat memastikan bahwa keamanan transaksi perhitungan ulang ini terbatas untuk satu tempat (dan juga membatasi keamanan di tabel saldo sehingga hanya rutin posting yang dapat menulisnya).
Kemudian simpan data historis sebanyak yang diperlukan oleh audit, layanan pelanggan, dan persyaratan kinerja.
sumber
Di sisi lain, ada masalah yang sering kita hadapi dalam perangkat lunak akuntansi. Diparafrasekan:
Jawabannya tentu saja bukan Anda tidak. Ada beberapa pendekatan di sini. Salah satunya adalah menyimpan nilai yang dihitung. Saya tidak merekomendasikan pendekatan ini karena bug perangkat lunak yang menyebabkan nilai yang salah sangat sulit dilacak sehingga saya akan menghindari pendekatan ini.
Cara yang lebih baik untuk melakukannya adalah apa yang saya sebut pendekatan log-snapshot-agregat. Dalam pendekatan ini, pembayaran dan penggunaan kami adalah sisipan dan kami tidak pernah memperbarui nilai-nilai ini. Secara berkala kami mengumpulkan data selama periode waktu dan menyisipkan rekaman snapshot yang dihitung yang mewakili data pada saat snapshot menjadi valid (biasanya periode waktu sebelum sekarang).
Sekarang ini tidak melanggar aturan Codd karena seiring waktu snapshots mungkin kurang dari tergantung pada data pembayaran / penggunaan yang dimasukkan. Jika kami memiliki snapshot yang berfungsi, kami dapat memutuskan untuk membersihkan data berusia 10 tahun tanpa memengaruhi kemampuan kami untuk menghitung saldo saat ini berdasarkan permintaan.
sumber
Untuk alasan kinerja, dalam kebanyakan kasus, kita harus menyimpan saldo saat ini - jika tidak menghitungnya dengan cepat, pada akhirnya akan menjadi sangat lambat.
Kami menyimpan total total berjalan yang telah dihitung dalam sistem kami. Untuk menjamin bahwa angka selalu benar, kami menggunakan batasan. Solusi berikut telah disalin dari blog saya. Ini menggambarkan inventaris, yang pada dasarnya masalah yang sama:
Menghitung total yang berjalan sangat lambat, apakah Anda melakukannya dengan kursor atau gabungan segitiga. Sangat menggoda untuk melakukan denormalkan, untuk menyimpan total yang berjalan dalam kolom, terutama jika Anda sering memilihnya. Namun, seperti biasa ketika Anda melakukan denormalkan, Anda perlu menjamin integritas data yang didenormalisasi. Untungnya, Anda dapat menjamin integritas menjalankan total dengan kendala - selama semua kendala Anda tepercaya, semua total menjalankan Anda benar. Juga dengan cara ini Anda dapat dengan mudah memastikan bahwa saldo saat ini (total berjalan) tidak pernah negatif - menegakkan dengan metode lain juga bisa sangat lambat. Script berikut menunjukkan tekniknya.
sumber
Ini pertanyaan yang sangat bagus.
Dengan asumsi bahwa Anda memiliki tabel transaksi yang menyimpan setiap debit / kredit, tidak ada yang salah dengan desain Anda. Bahkan, saya telah bekerja dengan sistem telekomunikasi prabayar yang telah bekerja dengan cara ini.
Hal utama yang perlu Anda lakukan adalah memastikan bahwa Anda melakukan
SELECT ... FOR UPDATE
saldo saat AndaINSERT
mendebit / kredit. Ini akan menjamin saldo yang benar jika terjadi kesalahan (karena seluruh transaksi akan dibatalkan).Seperti yang telah ditunjukkan orang lain, Anda akan memerlukan snapshot saldo pada periode waktu tertentu untuk memverifikasi bahwa semua transaksi dalam jumlah periode tertentu dengan periode mulai / akhir saldo dengan benar. Tulis pekerjaan batch yang berjalan pada tengah malam di akhir periode (bulan / minggu / hari) untuk melakukan ini.
sumber
Saldo adalah jumlah yang dihitung berdasarkan aturan bisnis tertentu, jadi ya Anda tidak ingin menyimpan saldo tetapi menghitungnya dari transaksi pada kartu dan karenanya akun.
Anda ingin melacak semua transaksi pada kartu untuk audit dan pelaporan pernyataan, dan bahkan data dari sistem yang berbeda di kemudian hari.
Intinya - hitung nilai apa saja yang perlu dihitung seperti dan ketika Anda perlu
sumber