Database-Design

複合主鍵是不好的做法嗎?

  • December 15, 2021

我想知道複合主鍵是否是不好的做法,如果不是,在哪些情況下使用它們是有益的?

我的問題是基於這篇文章

數據庫設計錯誤

注意關於復合主鍵的部分:

不良做法 6:複合主鍵

這是一個有爭議的觀點,因為現在許多數據庫設計人員都在談論使用整數 ID 自動生成的欄位作為主鍵,而不是由兩個或多個欄位組合定義的複合欄位。這目前被定義為“最佳實踐”,我個人傾向於同意它。

複合主鍵的圖像

然而,這只是一個約定,當然,DBE 允許定義復合主鍵,許多設計者認為這是不可避免的。因此,與冗餘一樣,複合主鍵是一種設計決策。

但是請注意,如果您的具有復合主鍵的表預計會有數百萬行,那麼控制複合鍵的索引可能會增長到 CRUD 操作性能非常下降的程度。在這種情況下,最好使用一個簡單的整數 ID 主鍵,其索引將足夠緊湊,並建立必要的 DBE 約束以保持唯一性。

說使用"Composite keys as PRIMARY KEY is bad practice"是胡說八道!

Composite PRIMARY KEYs 通常是一個非常“好東西”,並且是模擬日常生活中發生的自然情況的唯一方法!話雖如此,在許多情況下,使用複合 PK 會很麻煩且笨拙,因此不是最佳選擇。

您的問題是:(已"if composite primary keys are bad practice...回答)and if not, in which scenarios is their use beneficial?"

下面是一個範例,其中復合鍵代表 PK 的理性/有益選擇(確實是我看到的唯一理性的選擇 - 在這裡的小提琴中,還有一個額外的成績範例!

在復合鍵的有利方面,想想經典的 Databases-101 學生和課程教學範例以及許多學生學習的許多課程!

創建表課程和學生:

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)
);

我將以PostgreSQL 方言(和MySQL)為您提供範例 - 應該適用於任何稍加調整的伺服器。

現在,您顯然想要跟踪哪個學生正在學習哪個課程 - 所以您有所謂的 a joining table(也稱為、 或linkingbridging)。它們也被稱為更多技術術語!many-to-many``m-to-nassociative entities

1門課程可以有很多學生。

1名學生可以選修門課程。

所以,你創建一個連接表

CREATE TABLE registration
(
 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)
);

現在,明智地給出表格 a的唯一方法是將其組合為課程和學生。這樣,您將無法獲得:registration``PRIMARY KEY``KEY

  • 學生和課程組合的副本
  • 一門課程只能讓同一個學生註冊一次,並且
  • 一個學生只能報讀同一門課程一次
  • KEY您還可以對每個學生的課程進行現成的搜尋- AKA覆蓋​​索引
  • 找到沒有學生的課程和沒有參加課程的學生是微不足道的!

– db-fiddle範例將 PK 約束折疊到CREATE TABLE – 它可以通過任何一種方式完成。我更喜歡在CREATE TABLE聲明中包含所有內容。

ALTER TABLE registration
ADD CONSTRAINT registration_pk 
PRIMARY KEY (cs_course_id, cs_student_id);

現在,如果您發現按課程搜尋學生的速度很慢,可以使用UNIQUE INDEXon (sc_student_id, sc_course_id)。

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

添加索引沒有靈丹妙藥——它們會使s 和s 變慢,大大減少了時間!開發人員可以根據他們的知識和經驗來決定索引,但是說複合s總是不好是完全錯誤的。INSERT``UPDATESELECTPRIMARY KEY

在連接表的情況下,它們通常是唯一 PRIMARY KEY有意義的!連接表也經常是建模業務或自然或幾乎我能想到的每個領域中發生的事情的唯一方法!

此 PK 也covering index可用作有助於加快搜尋速度的工具。在這種情況下,如果人們經常在 (course_id, student_id) 上進行搜尋,這將特別有用,人們可以想像,這通常是這種情況!

這只是一個小例子,說明復合材料PRIMARY KEY可能是一個很好的主意,也是模擬現實的唯一明智方法!在我的腦海中,我能想到更多

我自己工作的一個例子!

考慮一個包含 flight_id、出發和到達機場列表以及相關時間的航班表,然後還有一個包含機組人員的cabin_crew 表!

可以建模的唯一PRIMARY KEY理智的方法是擁有一個以 flight_id 和 crowd_id 作為屬性的 flight_crew 表,唯一理智的是使用這兩個欄位的複合鍵!

引用自:https://dba.stackexchange.com/questions/188995