Ada beberapa alasan mengapa menggunakan satu "meja dewa" besar itu buruk. Saya akan mencoba dan mengilustrasikan masalah dengan database contoh yang dibuat. Anggaplah Anda mencoba membuat model acara olahraga. Kami akan mengatakan Anda ingin membuat model game dan tim yang bermain di game-game itu. Desain dengan beberapa tabel mungkin terlihat seperti ini (ini sengaja disederhanakan jadi jangan terjebak di tempat-tempat di mana lebih banyak normalisasi dapat diterapkan):
Teams
Id | Name | HomeCity
Games
Id | StartsAt | HomeTeamId | AwayTeamId | Location
dan database tabel tunggal akan terlihat seperti ini
TeamsAndGames
Id | TeamName | TeamHomeCity | GameStartsAt | GameHomeTeamId | GameAwayTeamId | Location
Pertama, mari kita lihat membuat indeks pada tabel tersebut. Jika saya membutuhkan indeks di kota asal untuk tim, saya bisa menambahkannya ke Teams
tabel atau TeamsAndGames
tabel dengan mudah. Ingat bahwa setiap kali Anda membuat indeks, yang perlu disimpan di disk di suatu tempat dan diperbarui saat baris ditambahkan ke tabel. Dalam hal Teams
tabel ini cukup mudah. Saya memasukkan tim baru, basis data memperbarui indeks. Tapi untuk apa TeamsAndGames
? Yah, hal yang sama berlaku dariTeams
contoh. Saya menambahkan tim, indeks diperbarui. Tapi itu juga terjadi ketika saya menambahkan game! Meskipun bidang itu akan menjadi nol untuk game, indeks tetap harus diperbarui dan disimpan di disk untuk game itu. Untuk satu indeks, ini kedengarannya tidak terlalu buruk. Tetapi ketika Anda membutuhkan banyak indeks untuk beberapa entitas yang dijejalkan ke dalam tabel ini, Anda membuang banyak ruang untuk menyimpan indeks dan banyak waktu prosesor memutakhirkannya untuk hal-hal yang tidak berlaku.
Kedua, konsistensi data. Dalam hal menggunakan dua tabel terpisah, saya bisa menggunakan kunci asing dari Games
tabel ke Teams
tabel untuk menentukan tim mana yang bermain dalam permainan. Dan dengan asumsi saya membuat HomeTeamId
dan AwayTeamId
kolom tidak dapat dibatalkan, basis data akan memastikan bahwa setiap permainan yang saya masukkan memiliki 2 tim dan bahwa tim-tim itu ada di basis data saya. Tapi bagaimana dengan skenario tabel tunggal? Nah, karena ada banyak entitas dalam tabel ini, kolom-kolom itu harus nullable (Anda bisa membuatnya tidak nullable dan mendorong data sampah di sana, tapi itu hanya ide yang mengerikan). Jika kolom tersebut tidak dapat dibatalkan, basis data tidak dapat lagi menjamin bahwa ketika Anda memasukkan game, ia memiliki dua tim.
Tetapi bagaimana jika Anda memutuskan untuk tetap melakukannya? Anda mengatur kunci asing sedemikian rupa sehingga bidang-bidang itu menunjuk kembali ke entitas lain dalam tabel yang sama. Tetapi sekarang database hanya akan memastikan bahwa entitas-entitas itu ada dalam tabel, bukan bahwa mereka adalah tipe yang benar. Anda bisa dengan mudah mengatur GameHomeTeamId
ke ID game lain dan database tidak akan mengeluh sama sekali. Jika Anda mencobanya dalam skenario beberapa tabel, basis data akan cocok.
Anda dapat mencoba mengurangi masalah ini dengan mengatakan "baiklah, kami hanya akan memastikan bahwa kami tidak pernah melakukannya dalam kode". Jika Anda yakin dengan kemampuan Anda untuk menulis kode bebas bug pertama kali dan dalam kemampuan Anda untuk memperhitungkan setiap kombinasi aneh dari hal-hal yang mungkin dicoba pengguna, silakan saja. Saya pribadi tidak yakin dengan kemampuan saya untuk melakukan hal-hal itu, jadi saya akan membiarkan database memberi saya jaring pengaman ekstra.
(Ini menjadi lebih buruk jika desain Anda adalah di mana Anda menyalin semua data yang relevan di antara baris daripada menggunakan kunci asing. Setiap ejaan / ketidakkonsistenan data lainnya akan sulit untuk diselesaikan. Bagaimana Anda bisa tahu apakah "Jon" adalah salah mengeja dari "John" "Atau jika itu disengaja (karena mereka adalah dua orang yang terpisah)?)
Ketiga, hampir setiap kolom perlu dibatalkan atau harus diisi dengan data yang disalin atau sampah. Gim tidak perlu TeamName
atau TeamHomeCity
. Jadi setiap game membutuhkan semacam placeholder di sana atau perlu dibatalkan. Dan jika itu nullable, database akan dengan senang hati mengambil game tanpa TeamName
. Ini juga akan membutuhkan tim tanpa nama, bahkan jika logika bisnis Anda mengatakan itu seharusnya tidak pernah terjadi.
Ada beberapa alasan lain mengapa Anda ingin tabel terpisah (termasuk menjaga kewarasan pengembang). Bahkan ada beberapa alasan mengapa tabel yang lebih besar mungkin lebih baik (denormalisasi kadang-kadang meningkatkan kinerja). Skenario-skenario itu sedikit dan jarang (dan biasanya paling baik ditangani ketika Anda memiliki metrik kinerja untuk menunjukkan bahwa itu benar-benar masalah, bukan indeks yang hilang atau yang lainnya).
Akhirnya, kembangkan sesuatu yang mudah dipelihara. Hanya karena "berfungsi" tidak berarti tidak apa-apa. Mencoba mempertahankan meja dewa (seperti kelas dewa) adalah mimpi buruk. Anda hanya menyiapkan diri Anda untuk kesakitan nanti.