khóa chính là một thực hành xấu? [đóng cửa]


14

Tôi muốn biết nếu các khóa chính tổng hợp là một thực tiễn xấu và nếu không, trên kịch bản nào được khuyến khích sử dụng.

Câu hỏi của tôi dựa trên bài viết này

lỗi thiết kế cơ sở dữ liệu

Phần về khóa chính tổng hợp:

Thực hành xấu số 6: Khóa chính tổng hợp

Đây là một điểm gây tranh cãi, vì hiện nay nhiều nhà thiết kế cơ sở dữ liệu nói về việc sử dụng trường tự động tạo số nguyên ID làm khóa chính thay vì tổng hợp được xác định bởi sự kết hợp của hai hoặc nhiều trường. Điều này hiện được định nghĩa là thực hành tốt nhất của người Viking và cá nhân tôi có xu hướng đồng ý với nó.

Hình ảnh của khóa chính tổng hợp

Tuy nhiên, đây chỉ là một quy ước và tất nhiên, DBE cho phép định nghĩa các khóa chính tổng hợp, điều mà nhiều nhà thiết kế nghĩ là không thể tránh khỏi. Do đó, như với sự dư thừa, các khóa chính tổng hợp là một quyết định thiết kế.

Mặc dù vậy, hãy cẩn thận, nếu bảng của bạn có khóa chính tổng hợp dự kiến ​​sẽ có hàng triệu hàng, chỉ mục kiểm soát khóa tổng hợp có thể tăng lên đến điểm mà hiệu suất hoạt động của CRUD bị suy giảm. Trong trường hợp đó, tốt hơn là sử dụng khóa chính ID số nguyên đơn giản có chỉ số sẽ đủ nhỏ gọn và thiết lập các ràng buộc DBE cần thiết để duy trì tính duy nhất.


4
Đây không phải là một thực hành "tốt" hay "xấu". Mỗi quyết định thiết kế phải phục vụ một mục đích; nếu bạn có thể giải thích (cho chính mình và những người khác) lý do tại sao bạn cần PK tổng hợp, bạn vẫn ổn. Ngược lại, nếu bạn có thể giải thích lý do tại sao bạn không cần nó, bạn cũng nên đi. Bài viết bạn liên kết để làm một công việc rất kém giải thích, theo quan điểm của tôi.
mustaccio

bài viết này báo hiệu một điểm, nhưng nếu chúng ta xem các khung phổ biến (ví dụ như đường ray) trong "thực tiễn tốt nhất" của nó thì không hỗ trợ loại khóa chính này, vậy tôi đã hỏi tại sao? đó là cho những khó khăn kỹ thuật hoặc một cái gì đó khác.
hackvan

Các thiết kế khung sẽ dễ dàng hơn khi chỉ hỗ trợ các khóa chính số nguyên đơn "đơn giản". Và vì hầu hết các nhà phát triển (ít nhất là theo kinh nghiệm cá nhân của tôi) không có nhiều về kỹ năng cơ sở dữ liệu (ít nhất là so với người dùng của trang web này), nên nó hoạt động đủ tốt cho hầu hết người dùng phần mềm. Vì hầu hết người dùng phần mềm không cần khóa tổng hợp (hoặc không nghĩ rằng họ cần, ít nhất là khi bắt đầu), nên họ có thể thoát khỏi việc không cung cấp hỗ trợ (tốt) cho khóa tổng hợp.
Willem Renzema

1
GUID tốt hơn INTEGER [Nối tiếp | Tự động khởi động | Danh tính | <anything_integer_you_like>]?
Vérace

4
Tôi sẽ không thuê tác giả đó
paparazzo

Câu trả lời:


31

Để nói rằng việc sử dụng "Composite keys as PRIMARY KEY is bad practice"là hoàn toàn vô nghĩa!

Các hỗn hợp PRIMARY KEYthường là một "điều tốt" và là cách duy nhất để mô hình hóa các tình huống tự nhiên xảy ra trong cuộc sống hàng ngày!

Hãy nghĩ về ví dụ giảng dạy Cơ sở dữ liệu-101 cổ điển của sinh viên và các khóa học và nhiều khóa học được thực hiện bởi nhiều sinh viên!

Tạo bảng khóa học và sinh viên:

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

Tôi sẽ cho bạn ví dụ trong phương ngữ PostgreSQL (và MySQL ) - sẽ hoạt động cho bất kỳ máy chủ nào có một chút điều chỉnh.

Bây giờ, bạn rõ ràng là muốn theo dõi trong đó học sinh được tham gia trong đó dĩ nhiên - vì vậy bạn có những gì được gọi là joining table(hay còn gọi là linking, many-to-manyhoặc m-to-nbảng). Họ cũng được biết đến như associative entitiestrong thuật ngữ kỹ thuật hơn!

1 khóa học có thể có nhiều sinh viên.
1 sinh viên có thể học nhiều khóa.

Vì vậy, bạn tạo một bảng tham gia

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

Bây giờ, cách duy nhất để đưa ra bảng này một cách hợp lý PRIMARY KEYlà biến nó KEYthành sự kết hợp giữa khóa học và sinh viên. Bằng cách đó, bạn không thể có được:

  • một bản sao của sự kết hợp giữa sinh viên và khóa học

    • một khóa học chỉ có thể có cùng một sinh viên đăng ký một lần, và

    • một sinh viên chỉ có thể đăng ký vào cùng một khóa học một lần duy nhất

  • bạn cũng có một tìm kiếm sẵn sàng KEYvề khóa học cho mỗi học sinh - AKA một chỉ số bao trùm ,

  • Thật là tầm thường khi tìm các khóa học mà không có học sinh và sinh viên không tham gia khóa học!

    - Ví dụ db-fiddle có ràng buộc PK được gấp lại thành BẢNG TẠO - Nó có thể được thực hiện theo một trong hai cách. Tôi thích có mọi thứ trong câu lệnh CREATE TABLE.


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

Bây giờ, bạn có thể, nếu bạn thấy rằng các tìm kiếm cho sinh viên theo khóa học là chậm, hãy sử dụng một UNIQUE INDEX(sc_student_id, sc_cference_id).

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

Không viên đạn bạc nào để thêm chỉ mục - chúng sẽ làm cho INSERTs và UPDATEs chậm hơn, nhưng với lợi ích lớn là thời gian giảm mạnhSELECT ! Tùy thuộc vào nhà phát triển quyết định lập chỉ mục dựa trên kiến ​​thức và kinh nghiệm của họ, nhưng để nói rằng PRIMARY KEYcác s composite luôn xấu thì hoàn toàn sai.

Trong trường hợp tham gia các bảng, chúng thường là duy nhất PRIMARY KEY có ý nghĩa! Tham gia các bảng cũng rất thường xuyên là cách duy nhất để mô hình hóa những gì xảy ra trong kinh doanh hoặc tự nhiên hoặc trong hầu hết mọi lĩnh vực tôi có thể nghĩ đến!

PK này cũng được sử dụng như một covering indexthứ có thể giúp tăng tốc tìm kiếm. Trong trường hợp này, nó sẽ đặc biệt hữu ích nếu một người tìm kiếm thường xuyên trên (Course_id, student_id), mà người ta có thể tưởng tượng, thường có thể là trường hợp!

Đây chỉ là một ví dụ nhỏ về việc một hỗn hợp PRIMARY KEYcó thể là một ý tưởng rất tốt và là cách duy nhất để mô hình hóa thực tế! Ngoài đỉnh đầu, tôi có thể nghĩ về nhiều thứ nữa.

Một ví dụ từ công việc của tôi!

Hãy xem xét một bảng chuyến bay có chứa một chuyến bay_id, một danh sách các sân bay khởi hành và đến và thời gian liên quan và sau đó là một bảng cabin_crew với các thành viên phi hành đoàn!

Cách duy nhất có thể được mô hình hóa này là có một bảng bay_crew với chuyến bay_id và crew_id như các tùy chọn và cách duy nhất PRIMARY KEYlà sử dụng khóa tổng hợp của hai trường!


2
trong ví dụ về khóa học và sinh viên, khóa học có thể có idkhóa chính và chỉ mục duy nhất cs_student_id cs_course_idvà có cùng kết quả không?
hackvan

2
Tại sao lãng phí tài nguyên làm điều đó? Với PK (Course_id, student_id), theo định nghĩa, bạn đã có một chỉ mục duy nhất trên các trường đó! Một chỉ mục duy nhất trên (student_id, Course_id) có thể được sử dụng để tăng tốc tìm kiếm - giả sử nếu bạn đang tìm kiếm những sinh viên không tham gia bất kỳ khóa học nào, nhưng quyết định đó có thể là một hoạt động, nhưng trong những ngày lưu trữ tương đối rẻ này, Tôi sẽ xem xét lại nó, đặc biệt là vì người ta sẽ nghĩ rằng bảng sẽ không được cập nhật rất thường xuyên.
Vérace

1
Đồng ý hoàn toàn cho các bảng liên kết - Tôi hiện đang làm việc với một số bảng. Tuy nhiên, khi tôi đội chiếc mũ C # của mình, tôi đang làm việc với trình tạo đảo ngược và xây dựng các lớp hữu ích (tìm, lưu, v.v.) cho lớp tiếp theo. Tôi gặp phải một vấn đề lớn - các khóa tổng hợp trở thành PITA vì có bất kỳ mã lưu / tìm chung chung nào. Có, có lẽ tôi có thể quay lại các tệp EDMX nhưng tôi vẫn cần xử lý mã trường hợp đặc biệt (đếm cột Pkey?) Hoặc thêm khóa thay thế nhân tạo (không thích và cần thêm các ràng buộc duy nhất :(). Vì vậy, tôi đoán mọi người không thích vật liệu tổng hợp đang nói từ mã lớp ứng dụng.
Richard Griffiths

Tùy thuộc vào tần suất chèn và tần suất của chỉ số defragmenetaion so với cửa sổ bảo trì, đây là giải pháp tốt hơn. Nhưng một số lựa chọn thiết kế là sự thỏa hiệp được thúc đẩy bởi các yêu cầu có thể không được nhìn thấy ngay lập tức. Nhưng như một bình luận đã nói, hãy xác định ưu / nhược điểm của cả hai kịch bản và đưa ra lựa chọn thiết kế.
Jonathan Fite

Điều gì xảy ra khi một sinh viên lặp lại khóa học? Sau đó, trừ khi các khóa học được phân tách kịp thời có các id khác nhau - thì bạn đã có một bảng ánh xạ khác. Hoặc thêm một trường cho ngày khóa học mà bây giờ phải được thêm vào khóa.
iheanyi

3

Mất nửa giáo dục của tôi: "khóa chính" không phải là khóa duy nhất được sử dụng để tra cứu dữ liệu trong bảng, mặc dù các công cụ quản lý dữ liệu sẽ cung cấp nó làm lựa chọn mặc định. Vì vậy, để chọn có một tổ hợp gồm hai cột hoặc một số được tạo ngẫu nhiên (có thể là nối tiếp) làm khóa bảng, bạn có thể có hai khóa khác nhau cùng một lúc.

Nếu các giá trị dữ liệu bao gồm một thuật ngữ duy nhất phù hợp có thể đại diện cho hàng, tôi thà khai báo đó là "khóa chính", ngay cả khi kết hợp, hơn là sử dụng khóa "tổng hợp". Khóa tổng hợp có thể hoạt động tốt hơn vì lý do kỹ thuật, nhưng lựa chọn mặc định của riêng tôi là chỉ định và sử dụng thuật ngữ thực sự làm khóa chính, trừ khi bạn thực sự cần phải đi theo cách khác để làm cho dịch vụ của bạn hoạt động.

Microsoft SQL Server có tính năng riêng biệt nhưng có liên quan của "chỉ mục cụm" điều khiển việc lưu trữ dữ liệu vật lý theo thứ tự chỉ mục và cũng được sử dụng bên trong các chỉ mục khác. Theo mặc định, khóa chính được tạo như một chỉ mục được phân cụm, nhưng bạn có thể chọn không phân cụm thay vào đó, tốt nhất là sau khi tạo chỉ mục được phân cụm. Vì vậy, bạn có thể có một cột nhận dạng số nguyên được tạo thành chỉ mục được nhóm, và, giả sử, tên tệp nvarchar (128 ký tự) làm khóa chính. Điều này có thể tốt hơn vì khóa chỉ mục được nhóm hẹp, ngay cả khi bạn lưu tên tệp dưới dạng thuật ngữ khóa ngoài trong các bảng khác - mặc dù ví dụ này là một trường hợp tốt để không làm điều đó.

Nếu thiết kế của bạn liên quan đến việc nhập các bảng dữ liệu bao gồm khóa chính bất tiện để xác định dữ liệu liên quan, thì bạn sẽ gặp khá nhiều khó khăn với điều đó.

https://www.techopedia.com/defTHER/5547/primary-key mô tả một ví dụ về việc chọn lưu trữ dữ liệu với số an sinh xã hội của khách hàng làm khóa khách hàng trong tất cả các bảng dữ liệu hay để tạo một khách hàng tùy ý khi bạn đăng ký chúng. Trên thực tế, đây là một sự lạm dụng nghiêm trọng đối với SSN, ngoài việc nó có hoạt động hay không; nó là một giá trị dữ liệu cá nhân và bí mật.

Vì vậy, một lợi thế của việc sử dụng thực tế trong thế giới thực là chìa khóa là không tham gia lại vào bảng "Khách hàng", bạn có thể truy xuất thông tin về họ trong các bảng khác - nhưng đó cũng là vấn đề bảo mật dữ liệu.

Ngoài ra, bạn sẽ gặp rắc rối nếu SSN hoặc khóa dữ liệu khác được ghi không chính xác, do đó bạn có giá trị sai trong 20 bảng bị ràng buộc thay vì chỉ trong "Khách hàng". Trong khi đó, khách hàng tổng hợp không có ý nghĩa bên ngoài nên không thể là một giá trị sai.


1
Tôi đặc biệt đánh giá cao sự quan sát rằng tùy thuộc vào dữ liệu khách hàng là khóa, thậm chí dữ liệu khách hàng duy nhất được biết đến (ở đây, SSN), sẽ bị hỏng nếu dữ liệu đó cần được sửa.
ToolmakerSteve
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.