Normalisasi: Apakah dianggap sesuai untuk membagi nilai numerik statis seperti setahun ke tabel mereka sendiri?

16

Saya melakukan diskusi yang menarik dengan desainer database lain tentang normalisasi. Dalam contoh ini, kami memiliki tabel GameTitles dan setiap catatan harus berisi tahun di mana game tersebut dirilis. Dia mengatakan 2NF mengamanatkan bahwa semuanya harus dinormalisasi, jadi, agar sesuai, bidang tahun harus dipecah menjadi tabel ReleaseYears dengan kunci primer sendiri yang dirujuk oleh tabel GameTitles. Saya mengatakan itu harus tetap sebagai bidang di tabel GameTitles itu sendiri.

Argumen saya untuk ini adalah bahwa satu tahun hanyalah nilai numerik non-primitif yang sifatnya statis (yaitu, 2011 akan selalu 2011). Karena ini, ia berfungsi sebagai pengidentifikasi sendiri dan tidak perlu referensi karena itu adalah apa adanya. Ini juga memperkenalkan pemeliharaan tambahan karena Anda sekarang harus menambahkan tahun baru ke tabel hanya untuk referensi saja. Jika Anda mengisi ulang tabel dengan rentang tahun yang luas maka Anda memiliki catatan tambahan yang berpotensi tidak memiliki referensi sama sekali. Ini juga meningkatkan ukuran basis data karena Anda sekarang memiliki tabel tambahan, catatan overhead, dan kunci utama tambahan untuk tahun itu sendiri. Jika Anda menyimpan tahun sebagai bidang di tabel GameTitles, Anda menghilangkan semua pemeliharaan dan overhead tambahan ini.

Pikiran tentang ini?

sunting: Dimaksudkan untuk memposting ini di StackOverflow. Dapatkah seseorang memilih untuk menghapus ini atau menandai untuk diperhatikan?

stoogemuffin
sumber
6
Kenapa begitu? sepertinya cocok di sini.
Leigh Riffel
Pertanyaan yang ingin saya tanyakan adalah apakah Anda menanyakan hal ini tentang normalisasi atau kebutuhan produksi aktual? Untuk produksi saya akan bertanya apakah itu hal yang sah untuk dilakukan?
jcolebrand

Jawaban:

14

Perancang basis data lainnya hanya salah, tetapi alasan Anda juga salah. Asumsikan Anda mulai dengan tabel ini, yang memiliki kunci kandidat tunggal, "game_title".

Table: game_titles

game_title                      year_first_released
--
The first game                  1998
The second game                 1999
Best game: the third one        2001
The fourth game                 2003
Forty-two, the end of games     2011

Anda mengevaluasi apakah itu ada di 2NF dengan bertanya pada diri sendiri pertanyaan-pertanyaan ini.

T: Pertama-tama, apakah ini di 1NF?

A: Ya, benar.

T: Apa atribut utama (atribut yang merupakan bagian dari kunci kandidat)?

A: "game_title" adalah satu-satunya atribut utama.

T: Apa atribut non-prima?

A: "year_first_released" adalah satu-satunya.

T: Apakah "year_first_released" secara fungsional tergantung pada keseluruhan "game_title", atau hanya sebagian saja?

A: Kunci kandidat tunggal, "game_title", adalah satu kolom; bahkan tidak memiliki bagian. Jadi "year_first_released" secara fungsional tergantung pada keseluruhan "game_title".

Voa. Anda telah menemukan 2NF.

Anda dapat memotong beberapa persyaratan formal dengan bertanya terlebih dahulu apakah ada di 1NF, dan kemudian menjawab pertanyaan ini.

T: Apakah ada kunci kandidat gabungan?

A: Tidak.

Voa. Anda telah menemukan 2NF lagi.

Menurut definisi, untuk tabel yang melanggar 2NF, harus memiliki setidaknya satu kunci kandidat yang memiliki lebih dari satu kolom.

Inilah alasan Anda menolak pendapat teman Anda.

  • Satu tahun hanyalah nilai numerik non-primitif.
  • Setahun sifatnya statis.
  • Setahun berfungsi sebagai pengidentifikasi sendiri.
  • Tabel tahun memperkenalkan pemeliharaan tambahan.
  • Tabel tahun mungkin memiliki baris tambahan yang tidak dirujuk.
  • Tabel tahun meningkatkan ukuran basis data.

Tidak satu pun dari alasan ini yang ada hubungannya dengan apakah tabel ada di 2NF.

Dalam mendesain basis data, tidak salah untuk mempertimbangkan masalah pemeliharaan, ukuran basis data, baris yang tidak direferensikan, batasan jangkauan, dan sebagainya. Itu hanya salah untuk menyebut hal-hal itu normalisasi.

Oh, dan tabel dua kolom yang saya berikan di atas - ada di 5NF.

Mike Sherrill 'Cat Recall'
sumber
2
Bagus sekali. Saya tergoda untuk mengirim jawaban yang mengatakan tidak lain dari kalimat pertama Anda ... "Perancang basis data lainnya salah", Anda telah membahas alasannya dengan sangat baik.
Mark Storey-Smith
5

Membuat tabel terpisah untuk atribut apa pun tidak ada hubungannya dengan normalisasi. 2NF, 3NF, BCNF, 4NF, 5NF semuanya berkaitan dengan menghilangkan ketergantungan non-kunci. Jika Anda menghapus atribut tunggal ke tabel baru dan menggantinya dengan atribut kunci asing maka dependensi dalam tabel secara logis akan sama seperti sebelumnya - sehingga versi tabel yang direvisi tidak lebih atau kurang dinormalisasi daripada itu sebelumnya.

nvogel
sumber
Saya ingin menambahkan sesuatu ke ini, tetapi tidak yakin apa. Anda mengatakan bahwa memindahkan sesuatu ke tabel yang memiliki korelasi 1: 1 (baik 1 kunci dengan nilai tepat 1 seperti dalam kasus ini, atau satu baris ke satu baris) tidak memberikan manfaat jika pencarian tidak diperlukan, bukan? Tetapi ada manfaat pencarian potensial jika Anda jarang membutuhkan tahun dan Anda hanya melihat kisaran 255 tahun atau kurang. Anda bisa saja lolos dengan beberapa byte yang disimpan di sini, tetapi karena biasanya itu dialokasikan pada 4bytes, ini bukan asumsi yang masuk akal.
jcolebrand
1
@ jcolebrand: Setuju dengan apa yang Anda katakan. Tetap saja jawabannya adalah sama: apakah Anda melakukannya atau tidak, tidak ada hubungannya dengan normalisasi.
nvogel
Saya setuju. Seperti saya katakan, milik saya agak setengah hati, "Saya merasa OP kehilangan sesuatu di sini" ... karena saya tidak yakin ke mana harus pergi dengan konsep itu.
jcolebrand
5

Dari sudut pandang saya, tabel tahun yang terpisah hanya akan masuk akal jika "tahun rilis" bukan tahun kalender, tetapi misalnya tahun fiskal yang mungkin mencakup beberapa tahun kalender (misalnya pergi dari Oktober hingga Oktober).

Tabel itu kemudian akan memuat definisi (awal dan akhir tanggal sebenarnya) tahun fiskal

seekor kuda tanpa nama
sumber
1
+1, Anda hanya perlu tabel jika ingin memiliki atribut :)
Jack Douglas
2

Dari http://en.wikipedia.org/wiki/Second_normal_form :

tabel 1NF berada di 2NF jika dan hanya jika, diberikan kunci kandidat K dan atribut A yang bukan merupakan konstituen dari kunci kandidat, A tergantung pada keseluruhan K daripada hanya bagian dari itu.

Anda tidak menunjukkan apakah tahun merupakan bagian dari kunci kandidat atau tidak, tapi saya tidak yakin itu penting, karena dalam kedua kasus 2NF akan dipenuhi sejauh tahun yang bersangkutan.

Pada tataran praktis, adalah ide yang buruk untuk memisahkan tahun dengan semua alasan yang Anda cantumkan.

Leigh Riffel
sumber
2

Saya tidak suka argumen terhadap tabel terpisah karena ukurannya atau bahwa itu akan memiliki baris yang tidak digunakan. Bahkan jika Anda menempatkan 1000 tahun ke dalam tabel ini, ukurannya akan diabaikan.

Yang mengatakan, saya tidak berpikir meja diperlukan sama sekali. Apa gunanya memiliki meja terpisah untuk tahun ini? Data ini sudah ada di tabel utama dan Anda sama sekali tidak menyimpan apa pun dengan membuat tabel kedua.

Argumen bisa berbeda untuk tabel kalender, di mana setiap baris mewakili satu hari dan dapat memiliki atribut lainnya (hari dalam seminggu, offset UTC, apakah itu hari libur, dll).

Tapi tahun saja? Nah, saya tidak melihat manfaat sama sekali ... Dan seperti yang orang lain tunjukkan, tanyakan kepada mereka mengapa mereka berpikir itu lebih normal? Atau apa yang mereka peroleh? Jika Anda mencoba menulis kueri suka

WHERE othertable.year = 2011

Dari pada

WHERE dt >= 20110101 AND dt < 20120101

Maka saya akan mencoba meyakinkan Anda bahwa yang terakhir jauh lebih baik untuk kinerja (dengan asumsi dt diindeks) dan penyimpanan. Jika kesederhanaan pengkodean adalah yang terpenting maka saya akan mengatakan kolom yang dikomputasi tetap akan lebih baik daripada tabel lain.

Aaron Bertrand
sumber
1

Saya sepenuhnya setuju dengan jawaban Catcall kecuali pada satu titik: "tahun" mungkin tidak selalu merupakan nilai primitif, tapi saya kira itu lebih merupakan konsep logika bisnis daripada desain basis data.

Menjaga desain yang sama, mari kita asumsikan bahwa tahun-tahun seharusnya hanya tahun-tahun yang diizinkan untuk dirilis. Sedemikian rupa, Anda tidak berurusan dengan nilai numerik primitif, melainkan subset dari mereka, dan karena subset tersebut tidak memiliki implementasi primitif, Anda harus melakukan sendiri (tabel terpisah?) Dan merujuknya (dengan FK). Sedemikian rupa, kita masih berbicara bertahun-tahun, tetapi kita perlu mengelolanya dengan cara yang berbeda, karena mereka secara konseptual mengubah artinya. Namun, mereka masih "tahun rilis", tetapi secara konseptual berbeda dalam hal apa artinya bagi seseorang dalam pengetahuan domain.

Untuk kasus khusus ini, saya sekali lagi mengatakan bahwa jawaban Catcall benar, tetapi hanya ingin menunjukkannya. (Maaf, belum cukup perwakilan untuk berkomentar.)

Alfa
sumber