Là một cột ID duy nhất cần thiết trong bảng nhiều-nhiều (ngã ba)?


22

Bắt đầu một vài dự án bắt đầu với EF, nhưng tôi có một số câu hỏi về bảng tham gia và khóa, v.v. Hãy nói rằng tôi có một bảng ứng dụng và bảng quyền. Các ứng dụng có nhiều quyền và mỗi quyền có thể thuộc về nhiều ứng dụng (nhiều-nhiều).

Bây giờ, các bảng Ứng dụng và Quyền rất dễ dàng:

Applications
--------------
PK  ApplicationID
    Name

Permissions
--------------
PK  PermissionID
    Name

Nhưng cách tốt nhất để làm bảng tham gia là gì? Tôi có hai lựa chọn sau:

ApplicationPermissions
-----------------------
PK  ApplicationPermissionID
CU  ApplicationID
CU  PermissionID

HOẶC LÀ

ApplicationPermissions
-----------------------
CPK ApplicationID
CPK PermissionID

PK = Primary Key
CPK = Composite Primary Key
CU = Composite Unique Index

Bạn đã bao giờ bị đốt cháy làm cách này hơn cách khác? Là nó ưu tiên nghiêm ngặt? Tôi nhận ra rằng rất nhiều "sự khác biệt" sẽ bị trừu tượng hóa bởi mẫu kho lưu trữ của tôi (ví dụ, tôi gần như sẽ không bao giờ tạo toàn bộ đối tượng cấp phép và thêm nó vào một ứng dụng, nhưng thực hiện bằng ID hoặc tên duy nhất hoặc một cái gì đó), nhưng tôi đoán tôi đang tìm kiếm những câu chuyện kinh dị, bằng cách này hay cách khác.

Câu trả lời:


20

Tôi tin rằng bạn có nghĩa là bảng "ngã ba", không phải bảng "tham gia".

Không cần bảng nối để có trường ID riêng. Bạn sẽ không bao giờ cần phải tham gia hoặc lọc trên một ID như vậy. Bạn sẽ chỉ tham gia hoặc lọc trên ID của các bảng bạn đang ánh xạ. ID trên bảng nối là một sự lãng phí không gian đĩa.

Vì vậy, tùy chọn "tốt nhất" là tránh ID. Thông thường một bảng nối sẽ có 2 chỉ số bao trùm. Mỗi chỉ số bao phủ sử dụng một trong các ID được ánh xạ làm trường sắp xếp chính.

Nhưng "tốt nhất" không phải là bởi một cú sút xa. Đây là một vấn đề rất nhỏ để có một trường ID dự phòng. Bạn sẽ không có bất kỳ câu chuyện kinh dị nào trên một lượng nhỏ đĩa bị lãng phí. ID sẽ không "đánh cắp" chỉ mục được nhóm vì dù sao bạn cũng không muốn phân cụm trên combo được ánh xạ.

Nếu khung của bạn muốn tất cả các bảng có ID, thì hãy tìm nó. Nếu các tiêu chuẩn cơ sở dữ liệu của nhóm bạn ra lệnh tất cả các bảng phải có ID thì hãy truy cập nó. Nếu không thì nên tránh nó.


2
Chà, bạn đã tuyên bố rằng việc thêm ID là một sự nhượng bộ nhỏ, dễ dàng vượt qua bởi các lợi ích tiềm năng, do đó, dường như với tôi rằng (có một ID duy nhất trong mỗi bảng là cách thực hành tốt nhất trong hầu hết các DBMS và ORM) bạn sẽ ủng hộ việc có ID là tùy chọn "tốt nhất" hoặc "mặc định", thay vì không có ID .
Robert Harvey

4
"Bạn sẽ không bao giờ cần phải tham gia hoặc truy vấn trên một ID như vậy" - nói rằng "không bao giờ" trong tình huống công nghệ đang mời điều đó xảy ra. Nói rằng, có những lúc bạn sẽ tham gia bảng tham gia đó (vâng, tôi đã nghe nói nó được gọi là bảng "tham gia" nhiều hơn bảng "ngã ba") cho đến một bảng thứ tư vì thực tế các thực thể được tham gia là một đối tượng kinh doanh của riêng họ.
Jesse C. Choper

4
@RobertHarvey. ID là một thực hành tốt cho các thực thể. Nhưng một điểm nối là một chi tiết triển khai cho nhiều mối quan hệ, không phải là một thực thể theo quyền riêng của nó. Nhưng như Jesse C. trượt chỉ ra, có những trường hợp một ngã ba có thể được coi là một thực thể kinh doanh.
mike30

1
"lãng phí không gian đĩa." - Tôi nghĩ rằng một số công cụ (InnoDB?) Dù sao cũng tạo một khóa chính (bên trong) nếu bạn không tự tạo một cái - vì vậy bạn có thể không thực sự có được dung lượng đĩa bằng cách không có.
Alex

@Alex. Bạn đặt một PK tổng hợp trên các ID được ánh xạ.
mike30

11

Trong nhiều năm, tôi đã có thói quen cho mỗi bảng "Tên bảng" một khóa chính được tạo tự động "TableNameID", không có bất kỳ ngoại lệ nào, thậm chí không có cho các bảng nối. Tôi có thể nói rằng tôi không bao giờ hối tiếc về điều đó, bởi vì nó làm cho mọi thứ dễ dàng hơn khi tạo mã chung làm một cái gì đó cho "tất cả các bảng" hoặc "một số bảng" hoặc cho "rất nhiều hàng của nhiều bảng khác nhau".

Ví dụ: nếu ai đó yêu cầu bạn lưu trữ một số hàng của các bảng khác nhau (hoặc tham chiếu đến các bảng) trong một tệp hoặc trong bộ nhớ, ví dụ, cho mục đích ghi nhật ký, sẽ rất tiện lợi khi bạn biết trước rằng bạn chỉ cần lưu trữ chính xác một bảng tên bảng & chính xác một ID số nguyên và bạn không phải đối phó với bất kỳ "trường hợp đặc biệt" nào.

Một điều nữa, khi bạn bắt đầu với các PK kết hợp, có thể đôi khi bạn sẽ gặp phải nhu cầu về các khóa ngoại kết hợp (vì bạn có thể đến một điểm mà bạn muốn thêm một tham chiếu FK vào ApplicationPermissionsbảng của mình ). Sau đó, yêu cầu tiếp theo có thể là phải có FK này là duy nhất kết hợp với các thuộc tính hoặc khóa ngoại khác - điều này sẽ dẫn đến tổng thể phức tạp tăng lên. Tất nhiên, không có gì là không thể xử lý đối với hầu hết các hệ thống DB hiện đại, nhưng một giải pháp thống nhất giúp cuộc sống cho các lập trình viên thường dễ dàng hơn rất nhiều.

Và cuối cùng, một câu lệnh như SELECT ... FROM TABLE WHERE TableNameID IN (id1,id2,...)hoạt động tốt với một cột duy nhất là khóa chính, nhưng tôi chưa bao giờ thấy một phương ngữ SQL nào cho phép bạn làm điều này với các khóa kết hợp. Nếu bạn biết trước rằng bạn sẽ không bao giờ cần một truy vấn như thế này, tốt thôi, nhưng đừng ngạc nhiên nếu ngày mai bạn nhận được một yêu cầu sẽ được giải quyết dễ dàng nhất với loại SQL này.

Tất nhiên, khi bạn mong đợi ApplicationPermissionsbảng của mình chứa hàng trăm triệu hàng, thì bạn nên xem xét để tránh một cái gì đó như a ApplicationPermissionsID.


Mặc dù tôi đã không chọn câu trả lời của bạn. Tôi thích các khía cạnh của nó. Cảm ơn những suy nghĩ của bạn (upvote).
solidau

6

Mặc dù câu trả lời của Mike là tốt, đây là những lý do tôi có thể thêm trường ID riêng hay không.

  1. Xem xét sử dụng một trường ID riêng cho bảng nối / nối nếu nó chứa các trường khác với ID . Điều này có xu hướng lưu ý rằng nó là một thực thể hạng nhất.

  2. Xem xét sử dụng một trường ID riêng nếu API hoặc bất kỳ logic hiện có nào có xu hướng sử dụng các trường đơn lẻ để truy xuất / chỉnh sửa các thực thể. Điều đó có thể giúp người khác theo dõi mã của bạn trong bối cảnh của một dự án lớn hơn.

  3. Đừng sử dụng nó nếu không có lợi ích cụ thể (KISS). EF biết cách xử lý loại bảng này và một ràng buộc duy nhất tổng hợp đôi khi có thể bị bỏ qua khi những người khác đang cố gắng hiểu loại mối quan hệ này. Ngoài ra, khi bình thường hóa, tôi cố gắng sử dụng khóa nhỏ nhất có thể xác định duy nhất bộ dữ liệu . Trong ví dụ thứ hai của bạn, bạn thực sự có 2 khóa chính ứng viên riêng biệt.


-5
table Person
   Id int identity(1,1) not null primary key
   ...other fields go here...
table Address
   Id int identity(1,1) not null primary key
   ...other fields go here...
table PersonAddress
   Id int identity(1,1) not null primary key
   PersonId int not null
   AddressId int not null

Hãy nhớ tạo một chỉ mục và khóa ngoại trên cả hai PersonIdAddressId.

Bất kể người khác nghĩ gì là "tốt hơn" hay "bạn nên", đây là cách đơn giản nhất và dễ nhất để cho phép cơ sở dữ liệu hoạt động đúng.


1
Tôi nghĩ một vấn đề với cách tiếp cận này là lược đồ cho phép hai PersonAddresshàng có giá trị PersonIdAddressIdgiá trị giống hệt nhau .
Sam
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.