Dalam perancangan database, tentunya kita sudah sering mendengar tentang "normalisasi" sebagai salah satu praktik penting dalam merancang struktur database. Saya pun ingat bahwa prinsip normalisasi ini sudah diajarkan sejak SMK atau kuliah di semester-semester awal. Normalisasi database dilakukan dengan tujuan mengurangi redundansi data (duplikasi data) yang tidak diperlukan, sehingga data yang disimpan akan lebih konsisten dan memudahkan maintenance kedepannya. Contoh normalisasi data dapat dilihat seperti berikut ini :
tb_customer
customer_id | customer_name | customer_phone |
---|---|---|
1 | Tian | 081234560000 |
2 | Rosa | 089999999999 |
tb_product
product_id | product_name | price |
---|---|---|
13 | Melon Juice | 10.000 |
15 | Apple Juice | 15.000 |
tb_transaction
transaction_id | transaction_date | customer_id | product_id | qty |
---|---|---|---|---|
1 | 2023-09-08 | 1 | 15 | 3 |
2 | 2023-09-08 | 2 | 13 | 2 |
Dalam contoh di atas, kita melihat penerapan normalisasi database dimana tabel utamanya adalah tb_transaction. Tabel tersebut berhubungan dengan tabel tb_product dengan key "tb_transaction.product_id = tb_product.product_id" dan tb_customer dengan key "tb_transaction.customer_id = tb_customer.customer_id" agar data yang disimpan di tabel tersebut tidak redundan.
Secara prinsip sebenarnya contoh implementasi tabel di atas sudah baik, akan tetapi dalam beberapa kasus (terutama ketika sudah menyentuh production), ada saat dimana kita harus keluar dari jalur normalisasi dan mempertimbangkan pendekatan yang berbeda, yaitu "Denormalisasi Database". Artikel kali ini akan membahas penerapan denormalisasi database secara lebih rinci, sebelumnya mari kita lihat masalah dari data yang ternormalisasi di atas.
Masalah dalam normalisasi database
Salah satu masalah yang cukup umum pada data normalisasi adalah hubungan master data dengan data transaksi. Dengan contoh tabel yang sudah dinormalisasi di atas: sekarang bayangkan apa yang akan terjadi ketika terjadi perubahan di data master customer atau product? Tentunya ketika menampilkan data transaksi akan otomatis berubah bukan? Tentu saja, karena memang itu tujuan dari normalisasi database. Terus masalahnya dimana?
Bayangkan misal suatu hari terjadi perubahan harga pada tb_product.product_id=15 yg awalnya seharga 15.000 menjadi 80.000. Ketika user menampilkan invoice di frontend yang membaca tabel "tb_transaction", nilai yang awalnya 15.000 x 3 = 45.000 TIBA-TIBA BERUBAH menjadi 80.000 x 3 = 240.000! Tentu saja ini adalah efek samping dari normalisasi data yang TIDAK SEHARUSNYA terjadi dalam tabel transaksi.
Selain itu bayangkan juga misal kita menghapus data tb_product.product_id=13 misal karena produk tsb sudah tidak dijual, apa yang terjadi ketika ada user yang menampilkan invoice di frontend dengan membaca tabel "tb_transaction" tersebut? Kemungkinannya cuma 2 : yang pertama adalah terjadi error karena ada data yang hilang, kemungkinan yang kedua adalah tidak error tapi data menjadi tidak muncul dengan semestinya.
Solusi : Denormalisasi
Setelah melihat celah di atas, apakah itu berarti normalisasi data itu tidak baik? Tentu saja bukan. Normalisasi data tetaplah merupakan prinsip penting yang wajib dilakukan dalam merancang database yang efisien, kecuali ada use-case tertentu dimana kita membutuhkan sebuah tabel yang dapat menampilkan data historical sekalipun terdapat perubahan pada master data. Jika normalisasi fokus mengurangi redundansi data dan meningkatkan efisiensi penyimpanan, maka denormalisasi sengaja menyimpan data redundan untuk mempercepat pengambilan data dan tidak terpengaruh pada perubahan di tabel relasi.
Apabila diklasifikasikan, berikut ini adalah pertimbangan kapan denormalisasi perlu dilakukan :
1. Untuk meningkatkan performance database
Database yang sudah sangat ternormalisasi mungkin memerlukan banyak operasi JOIN yang kompleks untuk mengambil data. Bayangkan saja misal untuk menampilkan data transaksi harus join ke 15 tabel sekaligus untuk mendapatkan data-data yang diinginkan (Ini bukan melebih-lebihkan, tapi sungguh real. Saat ini saya sedang menghandle project dengan database besar yang sangat ternormalisasi, dan struktur tabel tersebut sangat amat mengkesalkan). Hal ini tentu saja menambah load database dan memperlambat kinerja sistem, terutama saat menangani jumlah data yang besar. Dengan denormalisasi, SELECT data dapat menjadi lebih cepat karena data yang diperlukan sudah ada dalam satu tempat tanpa perlu melakukan JOIN kemanapun
2. Untuk memfasilitasi data historical
Apabila kita berhadapan dengan tabel master yang dapat terus berubah-ubah (contoh sederhananya: e-commerce dimana data produk dapat terus melakukan update harga), tabel yang denormalisasi dapat menampilkan data dengan baik dan konsisten sesuai dengan historical penyimpanannya. 1 relasi data yang sama dapat menampilkan nilai yang berbeda apabila memiliki nilai historical yang berbeda.
3. Untuk menampilkan skema data yang lebih intuitif
Dalam beberapa kasus, skema data yang sangat ternormalisasi dapat menjadi sulit dipahami karena harus menguasai relasi antar tabelnya. Dengan denormalisasi, skema data bisa lebih mirip dengan cara manusia memahami informasi, membuatnya lebih mudah untuk dipahami.
Sebagai contoh dengan pertimbangan di atas, tabel "tb_transaction" tadi dapat kita denormalisasikan menjadi seperti ini :
transaction_id | transaction_date | customer_id | customer_name | customer_phone | product_id | product_name | price | qty |
---|---|---|---|---|---|---|---|---|
1 | 2023-09-08 | 1 | Tian | 081234560000 | 15 | Apple Juice | 15.000 | 3 |
2 | 2023-09-08 | 2 | Rosa | 089999999999 | 13 | Melon Juice | 10.000 | 2 |
Sekarang kita bayangkan apa yang terjadi ketika semua harga di tabel "tb_product" mengalami kenaikan? Yang akan terjadi ketika transaksi baru dilakukan adalah kira-kira seperti ini:
transaction_id | transaction_date | customer_id | customer_name | customer_phone | product_id | product_name | price | qty |
---|---|---|---|---|---|---|---|---|
1 | 2023-09-08 | 1 | Tian | 081234560000 | 15 | Apple Juice | 15.000 | 3 |
2 | 2023-09-08 | 2 | Rosa | 089999999999 | 13 | Melon Juice | 10.000 | 2 |
3 | 2023-09-09 | 2 | Rosa | 089999999999 | 13 | Melon Juice | 30.000 | 3 |
4 | 2023-09-08 | 1 | Tian | 081234560000 | 15 | Apple Juice | 25.000 | 3 |
Dengan data yang denormalisasi seperti ini, ketika user menampilkan invoice dengan membaca tabel "tb_transaction" akan menampilkan data yang sangat relevan sesuai dengan nilai historicalnya. Ketika invoice tb_transaction.transaction_id=1 diakses maka nilainya tetap 45.000, karena harga tidak lagi dibaca dari tabel "tb_product.price", melainkan langsung dari kolom price yang sudah disimpan langsung.
Bahkan sekalipun data master customer & product dengan id yang sudah pernah disimpan dihapus, invoice dapat tetap muncul dengan benar karena seluruh data yang diperlukan sudah ada di tabel "tb_transaction" yang sudah didenormalisasi.
Kesimpulan
Penting untuk diingat bahwa denormalisasi harus digunakan dengan bijak. Jika tidak dikelola dengan baik, denormalisasi pun dapat menyebabkan masalah konsistensi data dan maintenance yang lebih kompleks. Dalam dunia yang terus berkembang ini, pengetahuan tentang normalisasi dan denormalisasi database adalah kunci untuk merancang dan mengelola database yang efisien. Selalu pertimbangkan manfaat dan risiko dari masing-masing pendekatan dan gunakan pendekatan yang sesuai dengan kebutuhan.