kunci primer komposit adalah praktik yang buruk? [Tutup]

14

Saya ingin tahu apakah kunci primer komposit adalah praktik yang buruk dan jika tidak, skenario mana yang disarankan untuk digunakan.

Pertanyaan saya didasarkan pada artikel ini

kesalahan desain database

Bagian tentang kunci primer komposit:

Praktik Buruk No. 6: Kunci Utama Komposit

Ini adalah semacam poin yang kontroversial, karena banyak perancang basis data saat ini berbicara tentang menggunakan bidang ID bilangan bulat yang dihasilkan secara otomatis sebagai kunci utama dan bukan kunci komposit yang ditentukan oleh kombinasi dua atau lebih bidang. Ini saat ini didefinisikan sebagai "praktik terbaik" dan, secara pribadi, saya cenderung menyetujuinya.

Gambar kunci primer komposit

Namun, ini hanya sebuah konvensi dan, tentu saja, DBE memungkinkan definisi kunci primer komposit, yang menurut banyak desainer tidak dapat dihindari. Oleh karena itu, seperti halnya redundansi, kunci primer komposit adalah keputusan desain.

Namun waspadalah, jika meja Anda dengan kunci primer komposit diharapkan memiliki jutaan baris, indeks yang mengendalikan kunci komposit dapat tumbuh hingga titik di mana kinerja operasi CRUD sangat menurun. Dalam hal ini, jauh lebih baik untuk menggunakan kunci primer ID integer sederhana yang indeksnya akan cukup kompak dan menetapkan batasan DBE yang diperlukan untuk mempertahankan keunikan.

retan
sumber
4
Ini bukan praktik "baik" atau "buruk". Setiap keputusan desain harus memenuhi tujuan; jika Anda dapat menjelaskan (kepada diri sendiri dan orang lain) mengapa Anda membutuhkan PK komposit, Anda dapat melakukannya. Sebaliknya, jika Anda bisa menjelaskan mengapa Anda tidak membutuhkannya, Anda juga bisa melakukannya. Artikel yang Anda tautkan melakukan pekerjaan yang sangat buruk menjelaskan, dalam pandangan saya.
mustaccio
artikel ini memberi isyarat, tetapi jika kita melihat kerangka kerja populer (seperti rel misalnya) dalam "praktik terbaik" tidak mendukung jenis kunci utama ini, jadi saya bertanya mengapa? ini untuk kesulitan teknis atau hal lain.
hackvan
Lebih mudah untuk desain kerangka untuk hanya mendukung kunci primer integer kolom tunggal "sederhana". Dan karena sebagian besar pengembang (setidaknya dalam pengalaman pribadi saya) tidak memiliki banyak dalam hal keterampilan basis data (setidaknya untuk pengguna situs ini, setidaknya), ini berfungsi cukup baik untuk sebagian besar pengguna perangkat lunak. Karena sebagian besar pengguna perangkat lunak tidak memerlukan kunci komposit (atau tidak berpikir mereka perlu, setidaknya di awal), maka mereka dapat lolos dengan tidak memberikan dukungan (baik) untuk kunci komposit.
Willem Renzema
1
Bagaimana GUID lebih baik daripada INTEGER [Serial | Auto_Increment | Identitas | <wh whatever_integer_you_like>]?
Vérace
4
Saya tidak akan mempekerjakan penulis itu
paparazzo

Jawaban:

31

Untuk mengatakan bahwa penggunaannya "Composite keys as PRIMARY KEY is bad practice"adalah omong kosong!

Komposit PRIMARY KEYsering kali merupakan "hal yang sangat baik" dan satu-satunya cara untuk memodelkan situasi alami yang terjadi dalam kehidupan sehari-hari!

Pikirkan contoh pengajaran Databases-101 klasik tentang siswa dan kursus dan banyak kursus yang diambil oleh banyak siswa!

Buat tabel kursus dan siswa:

CREATE TABLE course
(
  course_id SERIAL,
  course_year SMALLINT NOT NULL,
  course_name VARCHAR (100) NOT NULL,
  CONSTRAINT course_pk PRIMARY KEY (course_id)
);


CREATE TABLE student
(
  student_id SERIAL,
  student_name VARCHAR (50),
  CONSTRAINT student_pk PRIMARY KEY (student_id)
);

Saya akan memberi Anda contoh dalam dialek PostgreSQL (dan MySQL ) - harus bekerja untuk server apa pun dengan sedikit penyesuaian.

Sekarang, Anda jelas ingin melacak siswa mana yang mengambil kursus mana - jadi Anda memiliki apa yang disebut joining table(juga disebut linking, many-to-manyatau m-to-ntabel). Mereka juga dikenal sebagai associative entitiesjargon yang lebih teknis!

1 kursus dapat memiliki banyak siswa.
1 siswa dapat mengikuti banyak kursus.

Jadi, Anda membuat tabel bergabung

CREATE TABLE course_student
(
  cs_course_id INTEGER NOT NULL,
  cs_student_id INTEGER NOT NULL,

  -- now for FK constraints - have to ensure that the student
  -- actually exists, ditto for the course.

  CREATE CONSTRAINT cs_course_fk FOREIGN KEY (cs_course_id) REFERENCES course (course_id),
  CREATE CONSTRAINT cs_student_fk FOREIGN KEY (cs_student_id) REFERENCES student (student_id)
);

Sekarang, satu - satunya cara untuk memberikan tabel ini dengan bijaksana PRIMARY KEYadalah dengan membuat KEYkombinasi antara kursus dan siswa. Dengan begitu, Anda tidak bisa mendapatkan:

  • duplikat kombinasi siswa dan kursus

    • suatu kursus hanya dapat mendaftarkan siswa yang sama satu kali, dan

    • seorang siswa hanya dapat mendaftar di kursus yang sama satu kali saja

  • Anda juga memiliki pencarian yang sudah jadi KEYpada kursus per siswa - AKA indeks yang mencakup ,

  • itu sepele untuk menemukan kursus tanpa siswa dan siswa yang tidak mengambil kursus!

    - The db-biola misalnya memiliki kendala PK dilipat ke dalam CREATE TABLE - Hal ini dapat dilakukan dengan cara baik. Saya lebih suka memiliki semuanya dalam pernyataan CREATE TABLE.


ALTER TABLE course_student 
ADD CONSTRAINT course_student_pk 
PRIMARY KEY (cs_course_id, cs_student_id);

Sekarang, Anda bisa, jika Anda menemukan bahwa pencarian untuk siswa oleh kursus lambat, gunakan UNIQUE INDEXon (sc_student_id, sc_course_id).

ALTER TABLE course_student 
ADD CONSTRAINT course_student_sc_uq  
UNIQUE (cs_student_id, cs_course_id);

Tidak ada peluru perak untuk menambahkan indeks - mereka akan membuat INSERTs dan UPDATEs lebih lambat, tetapi pada manfaat besar kali sangat menurunSELECT ! Terserah pengembang untuk memutuskan untuk indeks yang diberikan pengetahuan dan pengalaman mereka, tetapi untuk mengatakan bahwa komposit PRIMARY KEYs yang selalu buruk hanya salah polos.

Dalam kasus bergabung dengan tabel, mereka biasanya satu - satunyaPRIMARY KEY yang masuk akal! Bergabung dengan tabel juga sangat sering menjadi satu-satunya cara untuk memodelkan apa yang terjadi dalam bisnis atau alam atau dalam hampir setiap bidang yang dapat saya pikirkan!

PK ini juga digunakan sebagai covering indexyang dapat membantu mempercepat pencarian. Dalam hal ini, akan sangat berguna jika seseorang mencari secara teratur di (course_id, student_id) yang, bisa dibayangkan, sering menjadi kasus!

Ini hanyalah contoh kecil di mana komposit PRIMARY KEYbisa menjadi ide yang sangat bagus, dan satu-satunya cara yang waras untuk memodelkan kenyataan! Dari atas kepala saya, saya bisa memikirkan banyak lagi.

Contoh dari pekerjaan saya sendiri!

Pertimbangkan tabel penerbangan yang berisi flight_id, daftar bandara keberangkatan dan kedatangan serta waktu yang relevan dan kemudian juga tabel cabin_crew dengan anggota kru!

Satu- satunya cara yang waras ini dapat dimodelkan adalah memiliki tabel flight_crew dengan flight_id dan crew_id sebagai attibutes dan satu-satunya yang waras PRIMARY KEYadalah dengan menggunakan kunci komposit dari dua bidang!

Vérace
sumber
2
dalam contoh kursus dan siswa, mungkin saja course_student memiliki idkunci utama dan indeks unik cs_student_id cs_course_iddan memiliki hasil yang sama?
hackvan
2
Mengapa sumber daya limbah melakukan itu? Dengan PK (course_id, student_id), menurut definisi Anda sudah memiliki indeks unik di bidang itu! Indeks unik pada (student_id, course_id) mungkin berguna dalam mempercepat pencarian - katakanlah jika Anda mencari siswa yang tidak mengambil kursus apa pun, tetapi keputusan itu bisa menjadi operasional, tetapi di masa penyimpanan yang relatif murah, Saya akan recoomend, terutama karena orang akan berpikir bahwa tabel tidak akan terlalu sering diperbarui.
Vérace
1
Setuju sepenuhnya untuk tabel tautan - Saya sedang mengerjakan beberapa saat ini. Namun, ketika saya mengenakan topi C # saya, saya bekerja dengan generator reversepoco dan membangun kelas yang berguna (temukan, simpan dll) untuk lapisan berikutnya. Saya mengalami masalah besar - kunci komposit menjadi PITA karena memiliki kode simpan / temukan generik. Ya, mungkin saya bisa kembali ke file EDMX tapi saya masih perlu bekerja di sekitar kode kasus khusus (menghitung kolom Pkey?) Atau menambahkan kunci pengganti buatan (tidak suka dan memerlukan batasan keunikan tambahan :(). Jadi, saya kira orang-orang yang tidak suka komposit berbicara dari kode lapisan Aplikasi
Richard Griffiths
Tergantung pada frekuensi memasukkan dan frekuensi defragmenetaion indeks vs jendela pemeliharaan, ini adalah solusi yang lebih baik. Tetapi beberapa pilihan desain adalah kompromi yang didorong oleh persyaratan yang mungkin tidak segera terlihat. Namun seperti yang dikatakan oleh satu komentar, identifikasi pro / kontra dari kedua skenario dan buat pilihan desain.
Jonathan Fite
Apa yang terjadi ketika seorang siswa mengulangi kursus? Kemudian, kecuali jika kursus yang terpisah dalam waktu mendapatkan id yang berbeda - maka Anda memiliki tabel pemetaan lain. Atau tambahkan bidang untuk tanggal kursus yang sekarang harus ditambahkan ke kunci.
iheanyi
3

Pandangan saya yang setengah berpendidikan: "kunci utama" tidak harus menjadi satu-satunya kunci unik yang digunakan untuk mencari data di tabel, meskipun alat manajemen data akan menawarkannya sebagai pilihan default. Jadi untuk memilih apakah memiliki gabungan dua kolom atau angka acak (mungkin serial) sebagai kunci tabel, Anda dapat memiliki dua kunci berbeda sekaligus.

Jika nilai data menyertakan istilah unik yang cocok yang dapat mewakili baris, saya lebih suka menyatakan itu sebagai "kunci utama", bahkan jika komposit, daripada menggunakan kunci "sintetis". Kunci sintetik mungkin berkinerja lebih baik karena alasan teknis, tetapi pilihan standar saya sendiri adalah untuk menunjuk dan menggunakan istilah nyata sebagai kunci utama, kecuali jika Anda benar-benar harus pergi ke arah lain untuk membuat layanan Anda berfungsi.

Microsoft SQL Server memiliki fitur berbeda tetapi terkait dari "indeks berkerumun" yang mengontrol penyimpanan fisik data dalam urutan indeks, dan juga digunakan di dalam indeks lain. Secara default, kunci utama dibuat sebagai indeks berkerumun, tetapi Anda dapat memilih bukan-berkerumun, lebih disukai setelah membuat indeks berkerumun. Jadi Anda dapat memiliki kolom yang dihasilkan identitas bilangan bulat sebagai indeks berkerumun, dan, katakanlah, nama file nvarchar (128 karakter) sebagai kunci utama. Ini mungkin lebih baik karena kunci indeks berkerumun sempit, bahkan jika Anda menyimpan nama file sebagai istilah kunci asing di tabel lain - meskipun contoh ini adalah kasus yang baik untuk juga tidak melakukan itu.

Jika desain Anda melibatkan mengimpor tabel data yang menyertakan kunci primer yang tidak nyaman untuk mengidentifikasi data terkait, maka Anda cukup terjebak dengan itu.

https://www.techopedia.com/definition/5547/primary-key menjelaskan contoh memilih apakah akan menyimpan data dengan nomor jaminan sosial pelanggan sebagai kunci pelanggan di semua tabel data, atau untuk menghasilkan customer_id sewenang-wenang ketika Anda daftarkan mereka. Sebenarnya, ini adalah pelanggaran berat terhadap SSN, selain dari itu berhasil atau tidak; ini adalah nilai data pribadi dan rahasia.

Jadi, keuntungan menggunakan fakta dunia nyata sebagai kuncinya adalah bahwa tanpa bergabung kembali ke tabel "Pelanggan", Anda dapat mengambil informasi tentang mereka di tabel lain - tetapi juga masalah keamanan data.

Selain itu, Anda dalam masalah jika SSN atau kunci data lainnya salah direkam, sehingga Anda memiliki nilai yang salah di 20 tabel terbatas dan bukan hanya di "Pelanggan". Sedangkan customer_id sintetis tidak memiliki makna eksternal sehingga tidak dapat menjadi nilai yang salah.

Robert Carnegie
sumber
1
Saya terutama menghargai pengamatan yang bergantung pada data pelanggan sebagai kunci, bahkan data pelanggan unik yang diketahui (di sini, SSN), rusak jika data itu perlu diperbaiki.
ToolmakerSteve