Saya ingin tahu apakah primary key komposit merupakan praktik yang buruk dan jika tidak, pada skenario mana yang direkomendasikan untuk digunakan.
Pertanyaan saya didasarkan pada artikel ini
Bagian tentang kunci primer komposit:
Praktik Buruk No. 6: Kunci Primer Komposit
Ini merupakan hal yang kontroversial, karena banyak perancang basis data saat ini berbicara tentang penggunaan field yang dibuat secara otomatis oleh ID integer sebagai kunci utama, bukan kunci komposit yang ditentukan oleh kombinasi dua atau lebih field. Hal ini saat ini didefinisikan sebagai "praktik terbaik" dan, secara pribadi, saya cenderung setuju dengan hal tersebut.
Namun, ini hanyalah sebuah konvensi dan, tentu saja, DBE mengizinkan definisi kunci primer komposit, yang menurut banyak desainer tidak dapat dihindari. Oleh karena itu, seperti halnya redundansi, kunci primer komposit adalah keputusan desain.
Namun berhati-hatilah, jika tabel Anda dengan kunci primer komposit diharapkan memiliki jutaan baris, indeks yang mengendalikan kunci komposit dapat tumbuh hingga mencapai titik di mana kinerja operasi CRUD menjadi sangat menurun. Dalam hal ini, jauh lebih baik menggunakan kunci primer ID integer sederhana yang indeksnya cukup ringkas dan menetapkan batasan DBE yang diperlukan untuk mempertahankan keunikan.
Mengatakan bahwa penggunaan `"Kunci komposit sebagai KUNCI UTAMA adalah praktik yang buruk" adalah omong kosong!
Komposit KUNCI UTAMA
sering kali merupakan hal yang sangat "baik" dan satu-satunya cara untuk memodelkan situasi alami yang terjadi dalam kehidupan sehari-hari!
Pikirkan contoh pengajaran Database-101 klasik tentang siswa dan mata kuliah dan banyak mata kuliah yang diambil oleh banyak siswa!
Buatlah tabel mata kuliah 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 memberikan Anda contoh dalam dialek PostgreSQL (dan MySQL) - dapat digunakan pada server manapun dengan sedikit penyesuaian.
Sekarang, Anda tentu saja ingin melacak siswa mana yang mengambil mata kuliah yang mana - jadi Anda memiliki apa yang disebut **tabel penggabungan`` (juga disebut
penghubung,
banyak-ke-banyakatau
m-ke-n). Mereka juga dikenal sebagai [
entitas asosiatif`]3 dalam jargon yang lebih teknis!
Sebuah mata kuliah 1 dapat memiliki banyak siswa.
Seorang siswa 1 dapat mengambil banyak mata kuliah.
Jadi, Anda membuat tabel gabungan
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 sebuah KUNCI UTAMA
secara bijaksana adalah dengan membuat KUNCI
tersebut menjadi kombinasi dari mata kuliah dan siswa. Dengan begitu, Anda tidak akan mendapatkannya:
duplikat dari kombinasi siswa dan mata kuliah
sebuah mata kuliah hanya dapat memiliki siswa yang sama yang terdaftar satu kali, dan
seorang siswa hanya dapat mendaftar di mata kuliah yang sama satu kali saja
Anda juga memiliki pencarian KEY
yang siap pakai untuk mata kuliah per siswa - AKA indeks penutup,
sangat mudah untuk menemukan mata kuliah tanpa siswa dan siswa yang tidak mengambil mata kuliah!
-- Db-biola contoh memiliki batasan PK yang dilipat ke dalam CREATE TABLE -- Bisa dilakukan dengan dua cara. Saya lebih suka memasukkan semuanya ke dalam pernyataan CREATE TABLE.
ALTER TABLE course_student
ADD CONSTRAINT course_student_pk
PRIMARY KEY (cs_course_id, cs_student_id);
Sekarang, Anda dapat, jika Anda menemukan bahwa pencarian siswa berdasarkan mata kuliah berjalan lambat, gunakan UNIQUE INDEX
pada (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 solusi yang tepat untuk menambahkan indeks - indeks tersebut akan membuat proses INSERT
dan UPDATE
menjadi lebih lambat, namun dengan manfaat yang besar yaitu mengurangi waktu SELECT
secara signifikan! Terserah kepada pengembang untuk memutuskan untuk mengindeks berdasarkan pengetahuan dan pengalaman mereka, tetapi untuk mengatakan bahwa komposit KUNCI UTAMA
adalah selalu buruk adalah salah besar.
Dalam kasus penggabungan tabel, mereka biasanya merupakan satu-satunya KUNCI UTAMA
yang masuk akal! Tabel gabungan juga sering kali menjadi satu-satunya cara untuk memodelkan apa yang terjadi dalam bisnis atau alam atau di hampir semua bidang yang dapat saya pikirkan!
PK ini juga berguna sebagai indeks penutup
yang dapat membantu mempercepat pencarian. Dalam hal ini, akan sangat berguna jika seseorang mencari secara teratur pada (course_id, student_id) yang, bisa dibayangkan, sering kali terjadi!
Ini hanyalah contoh kecil di mana gabungan KUNCI UTAMA
dapat menjadi ide yang sangat bagus, dan satu-satunya cara yang masuk akal untuk memodelkan kenyataan! Di luar kepala saya, saya dapat memikirkan banyak sekali contoh lainnya.
Contoh dari karya saya sendiri!
Pertimbangkan sebuah tabel penerbangan yang berisi flight_id, daftar bandara keberangkatan dan kedatangan dan waktu yang relevan dan kemudian juga sebuah tabel awak kabin dengan anggota kru!
Satu-satunya cara yang masuk akal untuk memodelkan hal ini adalah dengan memiliki tabel flight_crew dengan flight_id dan crew_id sebagai atribut dan satu-satunya KUNCI UTAMA
yang masuk akal adalah dengan menggunakan kunci komposit dari kedua field tersebut!
Pendapat saya yang setengah berpendidikan: "primary key" tidak harus menjadi satu-satunya kunci unik yang digunakan untuk mencari data dalam tabel, meskipun alat manajemen data akan menawarkannya sebagai pilihan default. Jadi, untuk memilih apakah akan menggunakan gabungan dari dua kolom atau nomor acak (mungkin serial) yang dihasilkan sebagai kunci tabel, Anda dapat memiliki dua kunci yang berbeda sekaligus.
Jika nilai data termasuk istilah unik yang sesuai yang dapat mewakili baris, saya lebih suka mendeklarasikannya sebagai "kunci utama", meskipun komposit, daripada menggunakan kunci "sintetis". Kunci sintetis mungkin berkinerja lebih baik karena alasan teknis, tetapi pilihan default saya sendiri adalah menunjuk dan menggunakan istilah yang sebenarnya sebagai kunci utama, kecuali jika Anda benar-benar perlu melakukan hal lain untuk membuat layanan Anda berfungsi.
Microsoft SQL Server memiliki fitur yang berbeda namun terkait dengan "clustered index" 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 yang tidak berkerumun, sebaiknya setelah membuat indeks berkerumun. Jadi, Anda dapat memiliki kolom yang menghasilkan identitas bilangan bulat sebagai indeks berkerumun, dan, katakanlah, nama file nvarchar (128 karakter) sebagai kunci primer. Ini mungkin lebih baik karena kunci indeks berkerumun adalah sempit, bahkan jika Anda menyimpan nama file sebagai istilah kunci asing di tabel lain - meskipun contoh ini adalah kasus yang baik untuk tidak melakukan hal itu.
Jika desain Anda melibatkan pengimporan tabel data yang menyertakan primary key yang tidak nyaman untuk mengidentifikasi data terkait, maka Anda akan terjebak dengan hal tersebut.
https://www.techopedia.com/definition/5547/primary-key menjelaskan sebuah contoh untuk memilih apakah akan menyimpan data dengan nomor jaminan sosial pelanggan sebagai kunci pelanggan di semua tabel data, atau untuk menghasilkan customer_id sembarang ketika Anda mendaftarkannya. Sebenarnya, ini adalah penyalahgunaan SSN yang serius, terlepas dari apakah SSN berfungsi atau tidak; SSN merupakan nilai data yang bersifat 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 ini juga merupakan masalah keamanan data.
Selain itu, Anda juga akan mendapat masalah jika SSN atau kunci data lainnya tidak dicatat dengan benar, sehingga Anda akan memiliki nilai yang salah di 20 tabel yang dibatasi, bukan hanya pada "Customer" saja. Sedangkan customer_id sintetis tidak memiliki arti eksternal sehingga tidak mungkin salah.