Kerugian menggunakan kunci asing nullable daripada membuat tabel persimpangan

15

Katakanlah saya memiliki diagram ER berikut:

masukkan deskripsi gambar di sini

Sekarang jika saya mewakili hubungan menggunakan kunci asing Schoolmasuk Student, saya dapat memiliki NULLnilai (karena a Student tidak diharuskan untuk menjadi milik a School), misalnya:

masukkan deskripsi gambar di sini

Jadi cara yang benar (berdasarkan apa yang saya baca) adalah membuat tabel persimpangan untuk mewakili hubungan, misalnya:

masukkan deskripsi gambar di sini

Dengan cara ini, tidak ada NULLnilai yang bisa ditampilkan dalam tabel School_has_Student.

Tapi apa kerugian menggunakan kunci asing nullable daripada membuat tabel persimpangan?


Edit:

Saya keliru memilih ( school_id, student_id) menjadi kunci utama untuk School_has_Studenttabel, yang membuat hubungan banyak-ke-banyak. Kunci primer yang benar seharusnya student_id:

masukkan deskripsi gambar di sini

Tom
sumber
7
Tidak ada cara yang "benar". Hanya ada cara yang terbaik untuk kebutuhan Anda.
MetaFight
1
Saya setuju dengan Doc tentang premis yang salah, tetapi mungkin masih cukup jelas untuk dijawab?
MetaFight
Ada premis yang salah, tetapi cukup mudah untuk meluruskan dan menjelaskan perbedaannya.
Saya menarik kembali suara dekat saya, tetapi kalimat "Jadi cara yang benar (berdasarkan apa yang telah saya baca) adalah membuat tabel persimpangan untuk mewakili hubungan" memberi saya kesan Anda harus memberi tahu kami sumber strainge mana yang memberi tahu Anda bahwa ini adalah " jalan yang benar. Dalam setiap buku teks yang telah saya baca sebelumnya, cara kanonik untuk hubungan 1: n adalah kunci asing tunggal. Atau apakah Anda salah paham akan sesuatu?
Doc Brown
@ Doc Brown Saya tidak ingat di mana saya telah membacanya, tetapi saya yakin itu mengatakan bahwa tabel persimpangan adalah cara yang benar. Ngomong-ngomong, bisakah Anda memberi saya nama sebuah buku yang mengatakan bahwa hubungan 1: n (dengan partisipasi opsional di sisi: 1) harus diwakili menggunakan kunci asing tunggal, saya tertarik membaca apa yang mereka katakan tentang subjek ini.
Tom

Jawaban:

18

Kedua model mewakili hubungan yang berbeda.

Dengan menggunakan tabel gabung, Anda memodelkan hubungan banyak-ke-banyak.

Dengan menggunakan kunci asing sederhana, Anda memodelkan hubungan satu-ke-banyak.

Kerugian dari kunci asing nullable adalah tidak dapat memodelkan hubungan sebagai banyak-ke-banyak, jika itu yang ingin Anda capai.


Berdasarkan hasil edit Anda terhadap pertanyaan, Anda secara efektif membagi tabel siswa menjadi dua tabel dengan kunci yang sama. Saya biasanya melihat ini pada tabel yang memiliki terlalu banyak bidang, sehingga seseorang membaginya menjadi dua agar lebih mudah dikelola (saya menyebutnya meletakkan lipstik pada babi).

Dengan memecah tabel siswa, Anda membuat tabel kedua opsional karena catatan tidak perlu ada di tabel kedua. Yang sangat mirip dengan bidang yang tidak perlu diatur karena itu bisa nol.

Jika Anda menginginkan hubungan satu-ke-banyak, Anda jauh lebih baik menggunakan satu tabel dan membiarkan ID sekolah menjadi nol di tabel siswa. Tidak ada alasan untuk menghindari null di bidang, bahkan untuk kunci asing. Itu menandakan bahwa hubungan luar negeri adalah opsional: pengembang dan DBA memahami dengan jelas, dan mesin basis data yang mendasarinya pasti akan berfungsi dengan baik.

Jika Anda khawatir tentang bergabung, jangan khawatir. Ada semantik yang didefinisikan dengan baik untuk bagaimana bergabung bekerja dengan bidang nol. Dengan menggunakan satu tabel, Anda dapat bergabung dengan dua tabel, bukan tiga.


sumber
Jadi jika saya memodelkan hubungan satu-ke-banyak (dengan partisipasi opsional di: 1 sisi), saya harus menggunakan kunci asing terlepas dari kenyataan bahwa itu dapat memiliki NULLnilai?
Tom
1
@Tom ya, itulah cara memodelkannya. Meskipun secara teknis memungkinkan untuk menggunakan tabel bergabung, model data memungkinkan banyak ke banyak sehingga Anda akan memerlukan pemicu dan logika database untuk mencegahnya. Anda lebih baik dengan membatasi hubungan dengan cara yang tidak mungkin untuk menambahkan data yang salah.
1
Saya mengedit pertanyaan saya. Saya hanya membuat student_idkunci utama dalam School_has_Studenttabel, yang menjaga hubungan sebagai satu-ke-banyak. Kelemahan apa yang dimiliki metode ini dibandingkan menggunakan kunci asing?
Tom
@ Tom saya mengedit jawaban saya.
6

Anda menulis dalam komentar di atas:

buku "Dasar-dasar Sistem Basis Data" [...] mengatakan [...] bahwa disarankan untuk menggunakan tabel persimpangan jika ada banyak nilai NULL di kolom kunci asing (misalnya: jika 98% karyawan jangan mengelola departemen)

Ketika ada banyak nilai NULL di kolom kunci asing, program Anda harus berurusan dengan kolom yang sebagian besar kosong ini untuk setiap catatan yang mereka proses. Kolom mungkin akan menempati beberapa ruang disk walaupun 98% dari semua kasusnya kosong, menanyakan hubungan berarti menanyakan kolom yang memberi Anda lebih banyak lalu lintas jaringan, dan jika Anda menggunakan ORM yang menghasilkan kelas dari tabel, program Anda juga akan membutuhkan lebih banyak ruang di sisi klien daripada yang diperlukan. Menggunakan tabel persimpangan menghindari ini, hanya akan ada catatan tautan yang diperlukan di mana kunci asing yang setara tidak akan menjadi NULL.

Menentang itu, jika Anda tidak hanya memiliki beberapa nilai NULL, katakanlah 50% atau lebih hubungan bukan NULL, menggunakan tabel persimpangan memberi Anda efek sebaliknya - lebih banyak ruang disk, kompleksitas yang lebih tinggi menghasilkan lebih banyak lalu lintas jaringan dll.

Jadi menggunakan tabel persimpangan hanyalah bentuk optimasi, hanya masuk akal untuk kasus tertentu, dan terutama saat ini, di mana ruang disk dan memori menjadi lebih murah, lebih jarang dibutuhkan. Perhatikan bahwa "Dasar-dasar Sistem Basis Data" awalnya ditulis lebih dari 20 tahun yang lalu (saya menemukan referensi ke edisi kedua dari 1994), dan saya kira rekomendasi itu sudah ada di sana pada waktu itu. Sebelum 1994, optimasi ruang mungkin jauh lebih penting daripada hari ini, karena penyimpanan massal masih lebih mahal dan komputer dan jaringan jauh lebih lambat daripada hari ini.

Sebagai catatan untuk komentar pemilih: pernyataan di atas hanya mencoba mengantisipasi apa yang ada dalam pikiran penulis "Fundamentals of Database Systems" dalam rekomendasinya, saya kira dia membuat pernyataan umum yang kasar, valid untuk sebagian besar sistem. Dalam beberapa database ada optimasi lain yang mungkin seperti "kolom jarang" yang membuat penggunaan tabel persimpangan bahkan lebih usang.

Jadi jangan salah rekomendasi itu. Buku ini tidak memberitahu Anda untuk memilih tabel persimpangan untuk {0,1}:nhubungan secara umum, atau - seperti yang Anda tulis - bahwa ini adalah "cara yang benar". Gunakan optimasi seperti ini yang akan membuat program Anda lebih rumit hanya ketika Anda benar-benar membutuhkannya.

Doc Brown
sumber
Anda berasumsi banyak tentang implementasi database, terutama mengingat OP tidak menyebutkan yang spesifik. Kemungkinan besar database cukup pintar untuk menggunakan hanya sedikit ruang untuk kolom yang jarang.
Gardenhead
@ardenhead: apa yang membuat Anda percaya bahwa ini "lebih dari mungkin"?
Doc Brown
Fakta bahwa basis data telah ada selama beberapa dekade dan sangat dioptimalkan karena merupakan komponen penting dari sebagian besar infrastruktur.
gardenhead
@gardenhead: menurut saya Anda membuat banyak asumsi yang tidak masuk akal dari saya. Namun demikian, lihat edit saya.
Doc Brown
2

Model konseptual akan terlihat seperti ini, yang sangat tidak lazim untuk dikatakan kurang:

masukkan deskripsi gambar di sini

Model fisik akan terlihat seperti ini, yang membingungkan untuk mengatakan lebih sedikit (orang akan berpikir itu M: M kecuali mereka melihat dari dekat):

masukkan deskripsi gambar di sini

Saran saya:

Jika Anda suka, banyak kolom (FK atau lainnya), yang tidak berlaku untuk sebagian besar siswa, pisahkan tabel menjadi tabel peran dengan rel 1: 1. Tapi itu bukan karena mereka adalah FK, itu karena kolom tidak berlaku untuk sebagian besar baris.

Kalau tidak , nullable FK adalah bagian normal dari database dan tabel join biasanya untuk rel M: M.

Penggunaan umum rel 1: 1 adalah untuk tabel peran yang memiliki kolom yang hanya berlaku jika entitas adalah tipe tertentu, dan mengekstraksi kolom BLOB untuk pertimbangan kinerja atau penyimpanan. Mengembalikan nilai null di FK bukan merupakan penggunaan umum untuk itu.

masukkan deskripsi gambar di sini

Tulains Córdova
sumber
2

Selain jawaban lain, saya ingin menunjukkan bahwa nilai nol untuk kunci asing bersifat mendua. Apakah itu berarti:

1) Sekolah siswa (jika ada) tidak diketahui (ini adalah arti standar 'null' - nilai tidak diketahui)

2) Diketahui apakah siswa memiliki sekolah atau tidak, dan mereka tidak memilikinya

Jika Anda menggunakan arti standar nol, bagaimana Anda mewakili "siswa tidak memiliki sekolah" dalam model kunci asing Anda. Jika demikian, Anda mungkin harus membuat entri "tidak sekolah", dengan id itu sendiri di tabel sekolah. (Tidak ideal)

Brad Thomas
sumber
2
Buku "Dasar-Dasar Sistem Basis Data" menyebutkan bahwa ada 3 interpretasi untuk NULL, itu bisa berarti: 1) Nilai tidak diketahui. 2) Nilai tidak tersedia atau ditahan. 3) Tidak atribut yang berlaku (saya pikir interpretasi ini berarti bahwa Anda dapat menentukan NULLkunci asing).
Tom
1
Itu daftar yang berguna tetapi semantik nol (atau nilai apa pun juga) dapat didefinisikan pengguna. Yaitu bisa berarti apa pun yang dikatakan perancang artinya, tidak terbatas pada daftar itu. Masalahnya adalah bagaimana membedakan makna yang berbeda ketika lebih dari satu mungkin diperlukan (atau bahkan disimpan secara tidak sengaja)
Brad Thomas
Jadi, apakah Anda menyarankan agar saya membuat tabel persimpangan daripada menggunakan kunci asing nullable?
Tom
@ Tom Ya, saya percaya itu lebih baik dalam kasus ini
Brad Thomas
@BradThomas - untuk menghindari ambiguitas yang sama saat menggunakan tabel persimpangan, apakah Anda mewakili kasus 2 (diketahui bahwa siswa tidak memiliki sekolah) dengan catatan di tabel persimpangan dengan NULL School_ID?
andrew
1

Tabel database memiliki hal yang disebut kendala ini. Jadi sangat mudah untuk membuat tabel persimpangan yang memungkinkan hanya 1 dari setiap siswa untuk muncul di tabel tetapi banyak sekolah di tabel itu. Secara efektif memberi Anda a

Teori itu bagus tetapi pada akhirnya Anda akan memodelkan basis data Anda setelah pertanyaan yang Anda ajukan.

Jika Anda ingin sering bertanya dengan pertanyaan: "siswa mana di sekolah saya", apakah Anda benar-benar ingin menanyakan seluruh tabel siswa atau memiliki tabel persimpangan yang mudah.

Dalam database: optimalkan untuk pertanyaan yang Anda ajukan.

Pieter B
sumber
0

Ada kasus penggunaan di mana menggunakan tabel ketiga sebenarnya bisa masuk akal. Contohnya mungkin murni hipotetis, tetapi saya harap ini menggambarkan poin saya dengan baik. Anggap Anda menambahkan lebih banyak kolom ke studentstabel dan pada titik tertentu, Anda memutuskan untuk menerapkan keunikan pada catatan melalui indeks komposit pada beberapa kolom. Sangat mungkin bahwa Anda harus memasukkan school_idkolom juga, dan di sini hal-hal mulai menjadi berantakan. Karena cara SQL dirancang, memasukkan beberapa catatan identik mana school_idadalah NULLakan mungkin. Masuk akal dari sudut pandang teknis, tetapi berlawanan dengan intuisi dan dapat menyebabkan hasil yang tidak terduga. Di sisi lain, menegakkan keunikan di atas meja persimpangan adalah mudah.

Saya harus memodelkan hubungan "opsional" seperti itu baru-baru ini, di mana persyaratan untuk kendala keunikan adalah karena kolom timestamp. Meninggalkan kunci asing yang dapat dibatalkan dalam tabel tiba-tiba mengarah pada kemungkinan memasukkan catatan dengan stempel waktu yang sama (mari kita asumsikan itu adalah default, set pada catatan yang belum diaudit / setujui) - dan satu-satunya jalan keluar adalah menghapus kolom nullable.

Jadi seperti yang Anda lihat, ini adalah kasus yang cukup spesifik, dan seperti yang dicatat orang lain, biasanya Anda akan baik-baik saja dengan semua NULLnilainya. Itu benar-benar tergantung pada persyaratan spesifik dari model Anda.

petkov.np
sumber
0

Selain banyak saran bagus yang sudah dikirimkan, secara pribadi saya bukan penggemar kunci asing kecuali mereka benar-benar diperlukan. Pertama ada hubungan M: M yang Anda referensikan. Plus, memanggil kunci asing, dan dengan demikian menarik data tabel itu ke dalam kueri Anda, memperkenalkan lebih banyak kerumitan dan tergantung pada ukuran tabel, kinerja lebih lambat. Seperti yang dikatakan orang lain, bidang FK yang tidak dapat dibatalkan dapat tidak didukung dan dapat membuat masalah integritas data.

Jika Anda mendefinisikan keadaan di mana sekolah siswa tidak diketahui atau kosong, NULL tidak akan membedakan kondisi tersebut. (Sekali lagi kita kembali ke integritas data.) Saran tabel peran oleh Tulains elegan dan memungkinkan nilai-nilai null bersih.

Aby Sheffer
sumber