Cách thực hành tốt nhất cho các khóa chính trong bảng là gì?


256

Khi thiết kế bảng, tôi đã phát triển thói quen có một cột duy nhất và tôi tạo khóa chính. Điều này đạt được theo ba cách tùy thuộc vào yêu cầu:

  1. Cột số nguyên mà tự động tăng.
  2. Mã định danh duy nhất (GUID)
  3. Cột một ký tự ngắn (x) hoặc số nguyên (hoặc loại số tương đối nhỏ khác) có thể đóng vai trò là cột định danh hàng

Số 3 sẽ được sử dụng để tra cứu khá nhỏ, chủ yếu là các bảng đọc có thể có mã chuỗi độ dài tĩnh duy nhất hoặc giá trị số như một năm hoặc số khác.

Đối với hầu hết các phần, tất cả các bảng khác sẽ có số nguyên chính tự động tăng hoặc số nguyên định danh duy nhất.

Câu hỏi :-)

Gần đây tôi đã bắt đầu làm việc với các cơ sở dữ liệu không có mã định danh hàng nhất quán và các khóa chính hiện đang được nhóm trên các cột khác nhau. Vài ví dụ:

  • thời gian / ký tự
  • datetime / số nguyên
  • datetime / varchar
  • char / nvarchar / nvarchar

Có một trường hợp hợp lệ cho điều này? Tôi đã luôn luôn xác định một danh tính hoặc cột định danh duy nhất cho những trường hợp này.

Ngoài ra, có rất nhiều bảng không có khóa chính. Các lý do hợp lệ, nếu có, cho điều này là gì?

Tôi đang cố gắng để hiểu tại sao các bảng được thiết kế như chúng, và nó dường như là một mớ hỗn độn lớn đối với tôi, nhưng có lẽ có những lý do tốt cho nó.

Một câu hỏi thứ ba để giúp tôi giải mã các câu trả lời: Trong trường hợp nhiều cột được sử dụng để bao gồm khóa chính, có một lợi thế cụ thể nào cho phương pháp này so với khóa thay thế / khóa nhân tạo không? Tôi đang suy nghĩ chủ yếu liên quan đến hiệu suất, bảo trì, quản trị, vv?


Tôi đã tìm thấy các kỹ năng cơ sở dữ liệu: Cách tiếp cận lành mạnh để chọn khóa chính là một bài đọc tốt và tôi tuân theo hầu hết các điểm đã nêu.
dùng2864740

Câu trả lời:


254

Tôi theo một vài quy tắc:

  1. Khóa chính phải nhỏ như cần thiết. Thích loại số vì loại số được lưu trữ ở định dạng nhỏ gọn hơn nhiều so với định dạng ký tự. Điều này là do hầu hết các khóa chính sẽ là khóa ngoại trong một bảng khác cũng như được sử dụng trong nhiều chỉ mục. Khóa của bạn càng nhỏ, chỉ mục càng nhỏ, bạn sẽ sử dụng càng ít trang trong bộ đệm.
  2. Khóa chính không bao giờ nên thay đổi. Cập nhật khóa chính phải luôn luôn nằm ngoài câu hỏi. Điều này là do nó hầu như được sử dụng trong nhiều chỉ mục và được sử dụng làm khóa ngoại. Cập nhật một khóa chính duy nhất có thể gây ra hiệu ứng gợn của các thay đổi.
  3. KHÔNG sử dụng "khóa chính vấn đề của bạn" làm khóa chính mô hình logic của bạn. Ví dụ số hộ chiếu, số an sinh xã hội hoặc số hợp đồng nhân viên vì những "khóa chính" này có thể thay đổi cho các tình huống trong thế giới thực.

Về thay thế so với khóa tự nhiên, tôi đề cập đến các quy tắc ở trên. Nếu khóa tự nhiên nhỏ và sẽ không bao giờ thay đổi, nó có thể được sử dụng làm khóa chính. Nếu khóa tự nhiên lớn hoặc có khả năng thay đổi, tôi sử dụng khóa thay thế. Nếu không có khóa chính, tôi vẫn tạo một khóa thay thế bởi vì kinh nghiệm cho thấy bạn sẽ luôn thêm các bảng vào lược đồ của mình và mong muốn bạn đặt một khóa chính đúng chỗ.


3
Tôi thích nó! Bạn có tài liệu nào cho cơ sở của "quy tắc" của mình không? Cảm ơn!
Lloyd Cotten

4
Không, chỉ là kinh nghiệm. Khi xử lý cơ sở dữ liệu "nhỏ", công cụ này không quan trọng lắm. Nhưng khi bạn đối phó với db lớn, tất cả những điều nhỏ nhặt đều quan trọng. Chỉ cần tưởng tượng nếu bạn có 1 tỷ hàng với pk int hoặc dài so với sử dụng văn bản hoặc hướng dẫn. Có một sự khác biệt rất lớn!
Logic

44
Chỉ cần nhớ đặt chỉ mục duy nhất đó vào khóa tự nhiên (nếu thực sự tồn tại thường không phải là trường hợp này) khi bạn sử dụng khóa nhân tạo.
HLGEM

3
@Lloyd Cotten: Đây là những gì một nhà cung cấp công cụ dữ liệu lớn nói để hỗ trợ cho quy tắc số 1: skyfoundry.com/forum/topic/24 . Nó thuyết phục tôi quay trở lại Ints
hobs

4
ngay cả khi bạn "biết" rằng "khóa tự nhiên là nhỏ và sẽ không bao giờ thay đổi", hãy suy nghĩ kỹ. "chúng tôi không bao giờ sử dụng lại các mã đó" là những từ cuối cùng nổi tiếng .... Về những điều duy nhất thuộc các loại nhỏ, không bao giờ thay đổi là iso và các tiêu chuẩn khác (mã quốc gia, mã sân bay iata,). Những thứ như "đại diện 2 chữ cái cho thương hiệu nội bộ này là gì" ... hãy suy nghĩ kỹ trước khi cho rằng "nó" sẽ không bao giờ thay đổi, bạn là một quyết định tài chính từ việc xây dựng lại cơ sở dữ liệu.
Đồi Andrew

90

Các khóa tự nhiên của câu thơ tự nhiên là một loại tranh luận tôn giáo trong cộng đồng cơ sở dữ liệu - xem bài viết này và các bài viết khác mà nó liên kết đến. Tôi không ủng hộ việc luôn có chìa khóa nhân tạo, cũng không bao giờ có chúng. Tôi sẽ quyết định trên cơ sở từng trường hợp cụ thể, ví dụ:

  • Các tiểu bang Hoa Kỳ: Tôi sẽ sử dụng state_code ('TX' cho Texas, v.v.), thay vì state_id = 1 cho Texas
  • Nhân viên: Tôi thường tạo ra một nhân viên nhân tạo, bởi vì thật khó để tìm thấy bất cứ điều gì khác hoạt động. SSN hoặc tương đương có thể hoạt động, nhưng có thể có các vấn đề như một người mới tham gia chưa cung cấp SSN của anh ấy / cô ấy.
  • Lịch sử tiền lương của nhân viên: (worker_id, start_date). Tôi sẽ không tạo một worker_salary_history_id nhân tạo. Điểm nào sẽ phục vụ (ngoài "tính nhất quán ngu ngốc" )

Bất cứ nơi nào sử dụng khóa nhân tạo, bạn cũng nên luôn khai báo các ràng buộc duy nhất trên các khóa tự nhiên. Ví dụ: sử dụng state_id nếu bạn phải, nhưng sau đó bạn nên khai báo một ràng buộc duy nhất trên state_code, nếu không, bạn chắc chắn cuối cùng sẽ kết thúc bằng:

state_id    state_code   state_name
137         TX           Texas
...         ...          ...
249         TX           Texas

9
Trong một số trường hợp với máy chủ SQL 2005/2008, khóa tự nhiên (văn bản) có thể nhanh hơn khóa int. Tôi có một ứng dụng có mã thân thiện 7-8 ký tự mà chúng tôi sử dụng làm khóa chính và nhanh hơn (và thường thuận tiện hơn) so với một đại diện thay thế. Dù sao chúng tôi cũng cần mã để chúng tôi có thể có mã dễ đọc / dễ nhớ của con người mà chúng tôi có thể chuyển một cách an toàn mà không bị xung đột sang một phiên bản ứng dụng khác (nhiều trang web tổng hợp thành một trang lớn hơn).
lambacck

1
+1 Câu trả lời hay. Tuy nhiên, tôi sẽ làm cho nhân viên nhân sự trở thành nguồn đáng tin cậy của một nhân viên nhận dạng, tức là nhân viên chịu trách nhiệm xác minh nhân viên trong cuộc sống thực, những người có khả năng sử dụng các định danh như SSN, tham khảo, v.v. Bộ phận nhân sự phải được tin cậy nguồn định danh nhân viên, không phải DBMS!
ngày

@ onedaywhen- Tôi sẽ không. tin tưởng cán bộ nhân sự. Mọi người rời đi, những người mới đến và có những ý tưởng khác nhau. Cung cấp cho họ quyền truy cập vào mã định danh mà họ cho là duy nhất / họ muốn sử dụng, nhưng bên trong cho db, dba nên tự đưa ra quyết định
Dave Pile

1
Lưu ý rằng SSN không nhất thiết phải là duy nhất ở mỗi quốc gia. Ít nhất là ở Áo, nhiều người có thể chia sẻ cùng một số
maja

Ngoài ra ở một số quốc gia (tôi nghĩ ngay cả ở Mỹ) họ thực sự khuyên không nên chia sẻ SSN.
Stijn de Witt

25

Chỉ cần một nhận xét thêm về một cái gì đó thường bị bỏ qua. Đôi khi không sử dụng khóa thay thế có lợi ích trong các bảng con. Giả sử chúng tôi có một thiết kế cho phép bạn điều hành nhiều công ty trong một cơ sở dữ liệu (có thể đó là một giải pháp được lưu trữ hoặc bất cứ điều gì).

Giả sử chúng ta có các bảng và cột này:

Company:
  CompanyId   (primary key)

CostCenter:
  CompanyId   (primary key, foreign key to Company)
  CostCentre  (primary key)

CostElement
  CompanyId   (primary key, foreign key to Company)
  CostElement (primary key)

Invoice:
  InvoiceId    (primary key)
  CompanyId    (primary key, in foreign key to CostCentre, in foreign key to CostElement)
  CostCentre   (in foreign key to CostCentre)
  CostElement  (in foreign key to CostElement)

Trong trường hợp bit cuối cùng không có ý nghĩa, Invoice.CompanyIdlà một phần của hai khóa ngoại, một cho bảng CostCentre và một cho bảng CostEuity . Khóa chính là ( InvoiceId , CompanyId ).

Trong mô hình này, không thể kết nối và tham khảo CostEuity từ một công ty và CostCentre từ một công ty khác. Nếu một khóa thay thế được sử dụng trên các bảng CostEuityCostCentre , thì nó sẽ như vậy.

Càng ít cơ hội để bắt vít, càng tốt.


6
Đây là một bất lợi được trích dẫn khi sử dụng các khóa thay thế. Nếu bảng có khóa thay thế, tôi vẫn có thể sử dụng nó cho các loại ràng buộc này. Thật không may, mặc dù ràng buộc yêu cầu một chỉ mục và thật kỳ lạ khi tạo một chỉ mục duy nhất trên (surrogate_key, other_column) khi (surrogate_key) là duy nhất. Ngoài ra, (other_column) thường hoàn toàn dư thừa trong bảng bản đồ vì (surrogate_key) là duy nhất ở nước ngoài. Người thay thế thực sự có thể muck mọi thứ lên.
Samuel Danielson

24

Tôi tránh sử dụng các khóa tự nhiên vì một lý do đơn giản - lỗi của con người. Mặc dù số nhận dạng duy nhất tự nhiên thường có sẵn (SSN, VIN, Số tài khoản, v.v.), nhưng chúng yêu cầu một người nhập chúng chính xác. Nếu bạn đang sử dụng SSN làm khóa chính, ai đó sẽ chuyển một vài số trong khi nhập dữ liệu và lỗi không được phát hiện ngay lập tức, thì bạn phải đối mặt với việc thay đổi khóa chính của mình.

Tất cả các khóa chính của tôi đều được xử lý bởi chương trình cơ sở dữ liệu trong nền và người dùng không bao giờ biết về chúng.


1
Tôi đã làm việc với một vài cơ sở dữ liệu sử dụng SSN hoặc ID thuế làm khóa chính. Không hiệu quả khi nói đến lưu trữ và tham chiếu khóa nước ngoài. Chưa kể rằng SSN của một người có thể thay đổi. Vì vậy, tôi hoàn toàn đồng ý với bạn.
Alex Jorgenson

13

Không có vấn đề gì trong việc tạo khóa chính của bạn từ nhiều lĩnh vực khác nhau, đó là Khóa tự nhiên .

Bạn có thể sử dụng cột Danh tính (được liên kết với một chỉ mục duy nhất trên các trường ứng cử viên) để tạo Khóa thay thế .

Đó là một cuộc thảo luận cũ. Tôi thích khóa thay thế trong hầu hết các tình huống.

Nhưng không có lý do gì để thiếu chìa khóa.

RE: EDIT

Vâng, có rất nhiều tranh cãi về điều đó: D

Tôi không thấy bất kỳ lợi thế rõ ràng nào về các phím tự nhiên, bên cạnh thực tế là chúng là sự lựa chọn tự nhiên. Bạn sẽ luôn nghĩ về Tên, SocialNumber - hoặc một cái gì đó tương tự - thay vì idPerson .

Khóa thay thế là câu trả lời cho một số vấn đề mà khóa tự nhiên gặp phải (chẳng hạn như thay đổi lan truyền).

Khi bạn đã quen với việc thay thế, nó có vẻ sạch sẽ hơn và dễ quản lý hơn.

Nhưng cuối cùng, bạn sẽ phát hiện ra rằng đó chỉ là vấn đề về hương vị - hay suy nghĩ -. Mọi người "nghĩ tốt hơn" với các phím tự nhiên và những người khác thì không thể.


13
Mọi người "nghĩ tốt hơn" với các phím tự nhiên. Máy móc và cơ sở dữ liệu, không.
FDCastel

11

Các bảng nên có một khóa chính tất cả các thời gian. Khi nó không phải là một trường AutoIncrement.

Đôi khi mọi người bỏ qua khóa chính vì họ truyền rất nhiều dữ liệu và nó có thể làm chậm (phụ thuộc vào cơ sở dữ liệu) quá trình. NHƯNG, nó nên được thêm vào sau nó.

Một số nhận xét về bảng liên kết , điều này đúng, đó là trường BUT ngoại lệ phải là FK để giữ tính toàn vẹn và một số trường hợp các trường đó cũng có thể là khóa chính nếu trùng lặp trong liên kết không được ủy quyền ... nhưng để giữ hình thức đơn giản vì ngoại lệ là một cái gì đó thường xuyên trong lập trình, khóa chính nên có mặt để giữ tính toàn vẹn của dữ liệu của bạn.


Tôi đồng ý. Và trong trường hợp phải chèn nhiều dữ liệu, hãy xóa ràng buộc khóa chính (hoặc sử dụng CHỨNG NHẬN BẬT trong TSQL) và đặt lại sau đó :)
Andrew Rollings

1
Có các trường hợp ngoại lệ: bảng liên kết rõ ràng
annakata

Một lý do khác: Nếu không có khóa PK / duy nhất, các trình duyệt bảng (ý tôi là, một cái gì đó như Access / SQL Server Management Studio) sẽ từ chối cập nhật / xóa một hàng với hàng trùng lặp. Bạn sẽ phải viết SQL cho điều đó.
Dennis C

Nó khá phổ biến để bỏ qua PK từ bảng thực tế kho dữ liệu. Trong Oracle, bạn có thể tham chiếu giả danh ROWID như một định danh duy nhất trong thời gian ngắn (nghĩa là không lưu trữ nó ở đâu đó và hy vọng nó sẽ không thay đổi)
David Aldridge

9

Bên cạnh tất cả những câu trả lời hay, tôi chỉ muốn chia sẻ một bài viết hay mà tôi vừa đọc, Cuộc tranh luận chính yếu .

Chỉ cần trích dẫn một vài điểm:

Nhà phát triển phải áp dụng một vài quy tắc khi chọn khóa chính cho mỗi bảng:

  • Khóa chính phải xác định duy nhất mỗi bản ghi.
  • Giá trị khóa chính của bản ghi không thể rỗng.
  • Giá trị khóa chính phải tồn tại khi bản ghi được tạo.
  • Khóa chính phải duy trì ổn định, bạn không thể thay đổi (các) trường khóa chính.
  • Khóa chính phải nhỏ gọn và chứa ít thuộc tính nhất có thể.
  • Giá trị khóa chính không thể thay đổi.

Phím tự nhiên (có xu hướng) phá vỡ các quy tắc. Khóa thay thế tuân thủ các quy tắc. (Bạn nên đọc qua bài viết đó, nó đáng để bạn dành thời gian!)


7

Khóa chính có gì đặc biệt?

Mục đích của một bảng trong một lược đồ là gì? Mục đích của một chìa khóa của một bảng là gì? Khóa chính có gì đặc biệt? Các cuộc thảo luận xung quanh các khóa chính dường như bỏ lỡ điểm khóa chính là một phần của bảng và bảng đó là một phần của lược đồ. Điều gì là tốt nhất cho các mối quan hệ bảng và bảng nên lái khóa được sử dụng.

Bảng (và mối quan hệ bảng) chứa thông tin về thông tin bạn muốn ghi lại. Những sự thật này nên khép kín, có ý nghĩa, dễ hiểu và không mâu thuẫn. Từ góc độ thiết kế, các bảng khác được thêm hoặc xóa khỏi lược đồ sẽ không ảnh hưởng đến bảng được đề cập. Phải có mục đích lưu trữ dữ liệu chỉ liên quan đến thông tin. Hiểu những gì được lưu trữ trong một bảng không cần phải trải qua một dự án nghiên cứu khoa học. Không có thực tế được lưu trữ cho cùng một mục đích nên được lưu trữ nhiều lần. Các khóa là toàn bộ hoặc một phần thông tin được ghi lại là duy nhất và khóa chính là khóa được chỉ định đặc biệt là điểm truy cập chính vào bảng (nghĩa là phải chọn để thống nhất và sử dụng dữ liệu, không chỉ chèn hiệu suất).

  • ASIDE: Hiệu ứng phụ không may của hầu hết các cơ sở dữ liệu được thiết kế và phát triển bởi các lập trình viên ứng dụng (mà đôi khi tôi) là những gì tốt nhất cho ứng dụng hoặc khung ứng dụng thường dẫn đến lựa chọn khóa chính cho các bảng. Điều này dẫn đến các khóa số nguyên và GUID (vì chúng đơn giản để sử dụng cho các khung ứng dụng) và các thiết kế bảng nguyên khối (vì chúng làm giảm số lượng các đối tượng khung ứng dụng cần thiết để biểu thị dữ liệu trong bộ nhớ). Các quyết định thiết kế cơ sở dữ liệu hướng ứng dụng này dẫn đến các vấn đề thống nhất dữ liệu quan trọng khi được sử dụng ở quy mô. Các khung ứng dụng được thiết kế theo cách này tự nhiên dẫn đến bảng tại một thiết kế thời gian. Các bản ghi một phần của Nhật Bản được tạo trong các bảng và dữ liệu được điền theo thời gian. Tương tác nhiều bảng được tránh hoặc khi được sử dụng gây ra dữ liệu không nhất quán khi ứng dụng hoạt động không đúng. Các thiết kế này dẫn đến dữ liệu vô nghĩa (hoặc khó hiểu), dữ liệu trải rộng trên các bảng (bạn phải xem các bảng khác để hiểu ý nghĩa của bảng hiện tại) và dữ liệu trùng lặp.

Người ta nói rằng các khóa chính nên nhỏ như cần thiết. Tôi sẽ nói rằng các phím chỉ nên lớn khi cần thiết. Nên tránh ngẫu nhiên thêm các trường vô nghĩa vào một bảng. Thậm chí còn tệ hơn khi tạo một khóa ra khỏi một trường vô nghĩa được thêm ngẫu nhiên, đặc biệt là khi nó phá hủy sự phụ thuộc nối từ một bảng khác sang khóa không chính. Điều này chỉ hợp lý nếu không có khóa ứng viên tốt trong bảng, nhưng sự xuất hiện này chắc chắn là dấu hiệu của một thiết kế lược đồ kém nếu được sử dụng cho tất cả các bảng.

Người ta cũng nói rằng các khóa chính sẽ không bao giờ thay đổi vì việc cập nhật khóa chính luôn luôn nằm ngoài câu hỏi. Nhưng cập nhật cũng giống như xóa theo sau là chèn. Theo logic này, bạn không bao giờ nên xóa một bản ghi khỏi một bảng bằng một khóa và sau đó thêm một bản ghi khác bằng một khóa thứ hai. Thêm khóa chính thay thế không loại bỏ thực tế là khóa khác trong bảng tồn tại. Cập nhật khóa không chính của bảng có thể phá hủy ý nghĩa của dữ liệu nếu các bảng khác có sự phụ thuộc vào ý nghĩa đó thông qua khóa thay thế (ví dụ: bảng trạng thái có khóa thay thế có mô tả trạng thái thay đổi từ 'Đã xử lý' thành 'Đã hủy 'chắc chắn sẽ làm hỏng dữ liệu). Điều cần phải luôn luôn ra khỏi câu hỏi là phá hủy ý nghĩa dữ liệu.

Đã nói điều này, tôi rất biết ơn về nhiều cơ sở dữ liệu được thiết kế kém tồn tại trong các doanh nghiệp ngày nay (những người khổng lồ vô nghĩa-khóa-dữ liệu-bị hỏng-dữ liệu-1NF), bởi vì điều đó có nghĩa là có vô số công việc cho những người hiểu thiết kế cơ sở dữ liệu phù hợp . Nhưng về mặt buồn, đôi khi điều đó khiến tôi cảm thấy như Sisyphus, nhưng tôi cá là anh ta có một khoản tiền trị giá 401k (trước khi gặp nạn). Tránh xa blog và trang web cho các câu hỏi thiết kế cơ sở dữ liệu quan trọng. Nếu bạn đang thiết kế cơ sở dữ liệu, hãy tìm kiếm Ngày của CJ. Bạn cũng có thể tham khảo Celko cho SQL Server, nhưng chỉ khi bạn giữ mũi trước. Về phía Oracle, tham khảo Tom Kyte.


1
"Theo logic này, bạn không bao giờ nên xóa một bản ghi khỏi một bảng bằng một khóa và sau đó thêm một bản ghi khác bằng một khóa thứ hai." - Có một trường hợp cho điều này, và đó chính là điều mà một điều khoản "BẬT XÓA HẠN CHẾ" trên một khóa ngoại sẽ làm. Trong một số trường hợp (giả sử bắt buộc phải có dấu vết kiểm toán), trường boolean "đã xóa" sẽ tốt hơn là cho phép bản ghi bị xóa.
Waz

6

Một chìa khóa tự nhiên, nếu có, thường là tốt nhất. Vì vậy, nếu datetime / char xác định duy nhất hàng và cả hai phần đều có ý nghĩa đối với hàng, điều đó thật tuyệt.

Nếu chỉ datetime là có ý nghĩa và char chỉ được xử lý để làm cho nó trở nên độc đáo, thì bạn cũng có thể chỉ cần đi với một trường xác định.


9
Thường tốt nhất? Tôi không có bất kỳ cơ sở khoa học nào nhưng hầu như mọi người đều tích cực thích khóa thay thế hơn là tự nhiên. Trong nhiều trường hợp không có chìa khóa tự nhiên.
JC.

3
Nên luôn luôn có một khóa tự nhiên cho bất kỳ hàng nào trong cơ sở dữ liệu của bạn. Khóa "tự nhiên" đó có thể là thứ được tạo ra trong thế giới kinh doanh hoặc bởi hệ thống kỹ thuật của bạn, nhưng nó phải luôn tồn tại.
Tom H

2
Nếu, trong thế giới của bạn, đó là những gì đã được xác định là cách duy nhất để xác định một hàng trong bảng, thì có. Tất nhiên, khi một nhà thiết kế chọn tạo GUID cho PK thì thường là do họ chưa hoàn thành công việc tìm khóa tự nhiên THỰC, vì vậy trong trường hợp đó, GUID KHÔNG phải là khóa tự nhiên.
Tom H

8
2. Nếu bạn lấy chìa khóa của mình từ thế giới tự nhiên, thế giới tự nhiên sẽ thay đổi để phá khóa của bạn. Nếu bạn sử dụng số điện thoại, bạn sẽ nhận được hai người dùng từ cùng một hộ gia đình. Nếu bạn sử dụng tên cuối cùng, họ kết hôn. Nếu bạn sử dụng SSN, luật riêng tư sẽ thay đổi và yêu cầu bạn xóa chúng.
James Orr

2
@ Khai thác: RE: # 2. nếu thế giới tự nhiên thay đổi và điều đó khiến cho khóa tự nhiên của bạn thay đổi, điều đó có nghĩa là bạn đã làm một công việc kém khi chọn khóa tự nhiên. Theo định nghĩa, khóa tự nhiên không thay đổi theo thời gian.
Tom H

6

Dưới đây là quy tắc riêng của tôi mà tôi đã giải quyết sau hơn 25 năm kinh nghiệm phát triển.

  • Tất cả các bảng nên có một khóa chính cột duy nhất tự động tăng.
  • Bao gồm nó trong bất kỳ chế độ xem nào có nghĩa là có thể cập nhật
  • Khóa chính không nên có bất kỳ ý nghĩa nào trong ngữ cảnh của ứng dụng của bạn. Điều này có nghĩa là nó không phải là SKU, số tài khoản hoặc id nhân viên hoặc bất kỳ thông tin nào khác có ý nghĩa đối với ứng dụng của bạn. Nó chỉ đơn thuần là một khóa duy nhất liên kết với một thực thể.

Khóa chính được cơ sở dữ liệu sử dụng cho mục đích tối ưu hóa và ứng dụng của bạn không nên sử dụng cho bất kỳ mục đích nào ngoài việc xác định một thực thể cụ thể hoặc liên quan đến một thực thể cụ thể.

Luôn luôn có một khóa chính giá trị duy nhất làm cho việc thực hiện các UPSERT rất đơn giản.

Sử dụng các chỉ mục bổ sung để hỗ trợ các khóa nhiều cột có ý nghĩa trong ứng dụng của bạn.


5

Các khóa tự nhiên so với nhân tạo đối với tôi là vấn đề bao nhiêu logic kinh doanh bạn muốn trong cơ sở dữ liệu của bạn. Số an sinh xã hội (SSN) là một ví dụ tuyệt vời.

"Mỗi khách hàng trong cơ sở dữ liệu của tôi sẽ và phải có SSN." Bam, xong rồi, biến nó thành khóa chính và được thực hiện với nó. Chỉ cần nhớ khi quy tắc kinh doanh của bạn thay đổi, bạn sẽ bị đốt cháy.

Bản thân tôi không thích khóa tự nhiên, do kinh nghiệm của tôi với việc thay đổi quy tắc kinh doanh. Nhưng nếu bạn chắc chắn nó sẽ không thay đổi, nó có thể ngăn một vài lần tham gia quan trọng.


8
Và tôi đã thấy dữ liệu trong đó SSN không phải là duy nhất mặc dù nó phải như vậy. Hãy cảnh giác với các khóa tự nhiên nếu bạn nhập dữ liệu của mình từ một nguồn khác!
HLGEM

2
Nếu bạn là đối tượng của hành vi trộm cắp danh tính, bạn có thể thay đổi số an sinh xã hội của mình. Có bốn tình huống nữa họ sẽ thay đổi số của bạn và chúng được liệt kê trên trang ssa.gov.
Zvi Twersky

4

Tôi nghi ngờ liệu pháp cuộn giấy của Steven A. Lowe là cần thiết cho người thiết kế cấu trúc dữ liệu gốc.

Bên cạnh đó, GUID là khóa chính có thể là một con lợn hiệu suất. Tôi sẽ không đề nghị nó.


2
Để nói một hog hiệu suất của nó là một tối ưu hóa sớm. Hướng dẫn được yêu cầu trong một số trường hợp (khách hàng bị ngắt kết nối, hợp nhất bảng trong tương lai, nhân rộng)
JC.

2
"Tối ưu hóa sớm" là cụm từ được sử dụng quá mức trên SO (IMHO)! Có, GUID có thể được yêu cầu trong MỘT SỐ trường hợp, nhưng Andrew có quyền chỉ ra rằng chúng không nên được sử dụng làm kiểu dữ liệu mặc định cho dù có yêu cầu hay không.
Tony Andrew

OK, nó không thực sự là một tối ưu hóa sớm. Ý tôi là hầu hết mọi người không trải nghiệm âm lượng cần thiết để nhận thấy sự khác biệt về hiệu suất. Có, sử dụng tính năng tự động nếu bạn biết bạn sẽ không bao giờ cần một hướng dẫn.
JC.

Hoặc sử dụng cả hai. Có khóa chính dựa trên int / long để chọn và tham gia nhanh, sau đó có trường hướng dẫn. Ít nhất, đó là những gì tôi đang làm. Điều này có sai không? Tôi có nên làm điều đó không? :)
Andrew Rollings

Tôi cũng đang sử dụng cả hai cột. Nhưng không chắc nó có sai hay không. Bạn có tìm thấy nó @AndrewRollings không?
YÒGÎ

3

Bạn nên sử dụng khóa chính 'tổng hợp' hoặc 'hỗn hợp' bao gồm nhiều trường.

Đây là một giải pháp hoàn toàn chấp nhận được, hãy vào đây để biết thêm thông tin :)


3

Tôi cũng luôn luôn sử dụng một cột ID số. Trong orory tôi sử dụng số (18,0) mà không có lý do thực sự nào ở trên số (12,0) (hoặc bất cứ điều gì là một số nguyên chứ không phải là một số dài), có lẽ tôi chỉ không muốn lo lắng về việc nhận được vài tỷ hàng trong các db!

Tôi cũng bao gồm một cột được tạo và sửa đổi (loại dấu thời gian) để theo dõi cơ bản, nơi nó có vẻ hữu ích.

Tôi không ngại thiết lập các ràng buộc duy nhất cho các kết hợp cột khác, nhưng tôi thực sự thích id của tôi, được tạo, yêu cầu cơ bản đã sửa đổi.


2
Tôi cũng phải chỉ ra rằng tôi không đặt ID trên các bảng liên kết / tham gia, chỉ trên các bảng có chứa dữ liệu.
JeeBee

3

Tôi tìm kiếm các khóa chính tự nhiên và sử dụng chúng ở nơi tôi có thể.

Nếu không tìm thấy khóa tự nhiên nào, tôi thích GUID hơn INT ++ vì SQL Server sử dụng cây và thật tệ khi luôn thêm khóa vào cuối cây.

Trên các bảng có nhiều khớp nối, tôi sử dụng khóa chính ghép của các khóa ngoại.

Vì tôi đủ may mắn để sử dụng SQL Server, tôi có thể nghiên cứu các kế hoạch thực hiện và thống kê với trình lược tả và trình phân tích truy vấn và tìm hiểu cách các khóa của tôi hoạt động rất dễ dàng.


Bạn có tài liệu nào để sao lưu tuyên bố này không: 'nếu không tìm thấy khóa tự nhiên nào, tôi thích GUID hơn INT ++ vì SQL Server sử dụng cây và thật tệ khi luôn thêm khóa vào cuối cây.' Không hoài nghi, chỉ cố gắng biên dịch một số tài liệu.
Lloyd Cotten

1
@Lloyd - Vui mừng khi bạn quan tâm đến một cái gì đó tôi thấy rất hấp dẫn bản thân mình. Một điểm khởi đầu tốt tại msdn.microsoft.com/en-us/l Library
ms177443 (MySQL.90) .aspx

2

Tôi luôn luôn sử dụng một autonumber hoặc trường nhận dạng.

Tôi đã làm việc cho một khách hàng đã sử dụng SSN làm khóa chính và sau đó vì các quy định của HIPAA đã buộc phải đổi thành "MemberID" và nó đã gây ra vô số vấn đề khi cập nhật khóa ngoại trong các bảng liên quan. Bám sát một tiêu chuẩn nhất quán của một cột danh tính đã giúp tôi tránh được một vấn đề tương tự trong tất cả các dự án của mình.


6
Nhà phát triển lựa chọn khóa tự nhiên không có nghĩa là khóa tự nhiên là xấu.
Tom H

1
Một công cụ khó sử dụng bằng cách nào đó không phải là một điểm chống lại công cụ đó?
Sqeaky

1

Tất cả các bảng nên có một khóa chính. Mặt khác, những gì bạn có là một HEAP - trong một số trường hợp, đây có thể là những gì bạn muốn (tải nặng khi dữ liệu được sao chép qua một nhà môi giới dịch vụ sang cơ sở dữ liệu hoặc bảng khác).

Đối với các bảng tra cứu có khối lượng hàng thấp, bạn có thể sử dụng mã 3 CHAR làm khóa chính vì việc này chiếm ít chỗ hơn INT, nhưng chênh lệch hiệu suất là không đáng kể. Ngoài ra, tôi sẽ luôn sử dụng INT trừ khi bạn có một bảng tham chiếu có lẽ có khóa chính tổng hợp được tạo từ các khóa ngoại từ các bảng liên kết.


1

Nếu bạn thực sự muốn đọc qua tất cả các cuộc tranh luận qua lại về cuộc tranh luận lâu đời này, hãy thực hiện tìm kiếm "khóa tự nhiên" trên Stack Overflow. Bạn sẽ nhận lại các trang kết quả.


1

GUID có thể được sử dụng làm khóa chính, nhưng bạn cần tạo đúng loại GUID để nó hoạt động tốt.

Bạn cần tạo HƯỚNG DẪN COMB. Một bài viết hay về nó và thống kê hiệu suất là Chi phí của GUID làm Khóa chính .

Ngoài ra, một số mã về xây dựng GUB COMB trong SQL nằm trong Uniqueidentifier so với nhận dạng ( lưu trữ ) .


5
IMHO, hướng dẫn chỉ nên được sử dụng khi bạn cần đồng bộ hóa dữ liệu trên các cơ sở dữ liệu. Trong đó một id được tạo tự động là có vấn đề. Sự khác biệt giữa việc sử dụng một hướng dẫn và sử dụng một kiểu số cơ bản là một hướng dẫn sẽ yêu cầu 16 byte mỗi hàng, trong khi một số sẽ nhỏ hơn nhiều.
Logic

Nếu bạn đi đến liên kết tôi đã cung cấp ở trên, có rất ít sự khác biệt về hiệu suất khi sử dụng Hướng dẫn COMB.
Donny V.

0

Chúng tôi thực hiện rất nhiều phép nối và khóa chính tổng hợp đã trở thành một con lợn hiệu suất. Một int đơn giản hoặc dài sẽ xử lý nhiều vấn đề mặc dù bạn đang giới thiệu khóa ứng viên thứ hai, nhưng việc tham gia trên một lĩnh vực so với ba lĩnh vực sẽ dễ dàng và dễ hiểu hơn nhiều.


1
Chiến lược này sụp đổ khi bạn phải duyệt qua 6 bảng để tham gia hai bảng thực tế mà bạn cần vì các khóa tổng hợp không được truyền bá. Nó cũng kết thúc yêu cầu sử dụng các vòng lặp / con trỏ cho nhiều lần chèn có thể là một con lợn hiệu suất HUGE.
Tom H

2
Tôi không lớn để học một cái gì đó mới. Tôi rất muốn xem một ví dụ về những gì bạn đang nói, sẽ rất hữu ích khi đưa một chút thực tế hợp lý vào một số trong những tranh luận tôn giáo này.
Dan Blair

0

Tôi sẽ thẳng thắn về sở thích của tôi đối với các khóa tự nhiên - sử dụng chúng khi có thể, vì chúng sẽ giúp cuộc sống quản trị cơ sở dữ liệu của bạn dễ dàng hơn rất nhiều. Tôi đã thiết lập một tiêu chuẩn trong công ty của chúng tôi rằng tất cả các bảng có các cột sau:

  • ID hàng (GUID)
  • Trình tạo (chuỗi; có mặc định tên người dùng hiện tại ( SUSER_SNAME()trong T-SQL))
  • Đã tạo (DateTime)
  • Dấu thời gian

Row ID có một khóa duy nhất trên mỗi bảng và trong mọi trường hợp là tự động được tạo trên mỗi hàng (và quyền ngăn mọi người chỉnh sửa nó) và được đảm bảo hợp lý là duy nhất trên tất cả các bảng và cơ sở dữ liệu. Nếu bất kỳ hệ thống ORM nào cần một khóa ID duy nhất, đây là một khóa để sử dụng.

Trong khi đó, PK thực tế, nếu có thể, là một khóa tự nhiên. Quy tắc nội bộ của tôi là một cái gì đó như:

  • Mọi người - sử dụng khóa thay thế, ví dụ INT. Nếu là nội bộ, người dùng Active Directory GUID là một lựa chọn chấp nhận được
  • Các bảng tra cứu (ví dụ StatusCodes) - sử dụng mã CHAR ngắn; nó dễ nhớ hơn INTs và trong nhiều trường hợp, các biểu mẫu và người dùng giấy cũng sẽ sử dụng nó để đơn giản (ví dụ Status = "E" cho "Đã hết hạn", "A" cho "Đã phê duyệt", "NADIS" cho "Không phát hiện amiăng Trong mẫu ")
  • Bảng liên kết - sự kết hợp của FK (ví dụ EventId, AttendeeId)

Vì vậy, lý tưởng là bạn kết thúc với một PK tự nhiên, dễ đọc và dễ nhớ của con người, và một GUID một ID-mỗi-bàn thân thiện với ORM.

Hãy cẩn thận: cơ sở dữ liệu tôi duy trì có xu hướng tới 100.000 hồ sơ thay vì hàng triệu hoặc hàng tỷ, vì vậy nếu bạn có kinh nghiệm về các hệ thống lớn hơn chống lại lời khuyên của tôi, vui lòng bỏ qua cho tôi!


1
Bạn có đề xuất tạo cả SK GUID INT SK cho các bảng không có khóa tự nhiên mạnh không?

Bạn không cần phải có, nhưng lợi ích là: a) nó giúp nhân rộng dễ dàng hơn nếu bạn cần, b) khi giao dịch với ORM, bạn có thể gán ID duy nhất cho đối tượng của mình trong mã trước khi lưu nó (rất hữu ích nếu bạn phải thực hiện nhiều chỉnh sửa trên đối tượng của bạn, có thể lưu vào bộ đệm trong phiên, trước khi lưu nó). Chìa khóa là INT trong bản năng này; GUID chỉ là một phần thưởng.
Keith Williams
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.