Có phải là một thực hành tốt để luôn luôn có một khóa chính số nguyên tự động?


191

Trong cơ sở dữ liệu của mình, tôi có xu hướng tập thói quen có khóa chính số nguyên tăng tự động với tên idcho mỗi bảng tôi tạo để tôi có một tra cứu duy nhất cho bất kỳ hàng cụ thể nào.

Đây có được coi là một ý tưởng tồi? Có bất kỳ nhược điểm để làm theo cách này? Đôi khi tôi sẽ có nhiều chỉ số như id, profile_id, subscriptionsnơi idlà định danh duy nhất, profile_idliên kết với nước ngoài idcủa một Profilebảng, vv

Hoặc có những kịch bản mà bạn không muốn thêm một lĩnh vực như vậy?


61
Có một cái nhìn về vấn đề xe tăng Đức cho một ví dụ trong đó một định danh tăng tự động đơn giản là một vấn đề. Tất nhiên điều này chỉ quan trọng nếu bạn đang sử dụng id của mình ở nơi công cộng.
Bergi

24
@ArukaJ Vấn đề là nó rò rỉ một số thông tin về hệ thống. Ví dụ: giả sử cơ sở dữ liệu chứa các bài đăng do người dùng viết, mỗi bài đăng có một id tuần tự. Giả sử bạn thực hiện bốn bài đăng, mỗi bài đăng có một id: lúc 4 giờ sáng (20), 5 giờ sáng (25), 8 giờ tối (100) và 9 giờ tối (200). Bằng cách nhìn vào các id, bạn có thể thấy rằng chỉ có 5 bài đăng được thêm vào từ 4 giờ sáng đến 5 giờ sáng, trong khi 100 bài được thêm vào từ 8 giờ tối đến 9 giờ tối. Nếu bạn đang cố chọn thời gian cho một cuộc tấn công từ chối dịch vụ, đó có thể là thông tin có giá trị.
Joshua Taylor

29
Đối với mọi người phàn nàn về "vấn đề xe tăng Đức" .... nếu điều duy nhất ngăn ai đó truy cập dữ liệu họ không nên là một khóa trong URL của bạn ... bạn có vấn đề lớn hơn GUID so với Auto INT.
Matthew Whited

11
@MatthewWhited Không chỉ là về việc hoán đổi các tham số trong một URL. Giả sử bạn sử dụng một trang web và bạn tạo tài sản 100 tại thời điểm tvà tài sản 120 tại thời điểm đó t + 60. Nếu bạn có thể thấy cả hai ID đó (100 và 120) ở dạng không bị ảnh hưởng, thì bây giờ bạn biết tổng số tài sản tồn tại, cũng như khoảng tốc độ chúng được tạo. Đây là rò rỉ thông tin. Đây không hoàn toàn là giả thuyết.
Chris Hayes

15
"Có phải là thực hành tốt để luôn luôn ..." Không
brian_o

Câu trả lời:


137

Không bao giờ là một ý tưởng tồi để có một định danh hàng duy nhất được đảm bảo. Tôi đoán tôi không nên nói không bao giờ - nhưng hãy đi với phần lớn thời gian đó là một ý tưởng tốt.

Nhược điểm tiềm năng lý thuyết bao gồm một chỉ số bổ sung để duy trì và không gian lưu trữ thêm được sử dụng. Điều đó không bao giờ là đủ lý do để tôi không sử dụng nó.


11
Đó là những gì tôi làm. Hầu hết mọi người đều sử dụng 'id' hoặc 'tablename_id' (chẳng hạn như user_id). Đối số thường không phải là nếu cột là cần thiết, nhưng cách đặt tên cho nó.
GrandmasterB

103
Cá nhân tôi nghĩ rằng tên bảng nên ngụ ý phần còn lại. TableName.idtrái ngược với TableName.TableName_id, bởi vì những gì khác idsẽ được đề cập đến? Nếu tôi có một trường id khác trong bảng thì tôi sẽ thêm tiền tố vào tên bảng nếu nó đề cập đến một bảng khác
AJJ

10
@ArukaJ bạn đã đề cập bạn đang sử dụng SQLite. Đó thực sự là một chút của một trường hợp đặc biệt, vì nó luôn tạo ra một cột như vậy 'dưới mui xe'. Vì vậy, bạn thậm chí không sử dụng bất kỳ không gian bổ sung nào vì bạn có một cái dù bạn muốn hay không. Ngoài ra, rowid của SQLite luôn là số nguyên 64 bit. Nếu sự hiểu biết của tôi về nó là chính xác, nếu bạn xác định một hàng tăng tự động, nó sẽ là bí danh cho hàng bên trong. Vì vậy, bạn có thể luôn luôn làm điều đó! Xem sqlite.org/autoinc.html
GrandmasterB

9
Một ngoại lệ tôi có thể nghĩ đến là nếu bạn có một mã định danh duy nhất được tạo theo một cách khác, trong trường hợp đó phải là khóa chính và id tăng tự động là dự phòng.
Ham HamJ

4
@GrandmasterB: Phiên bản hiện tại của SQLite cho phép tạo WITHOUT ROWIDcác bảng (có bản rõ ràng PRIMARY KEY) dưới dạng tối ưu hóa. Nhưng nếu không, một INTEGER PRIMARY KEYcột là bí danh cho rowid.
dan04

92

Tôi không đồng ý với tất cả các câu trả lời trước đây. Có nhiều lý do tại sao nên thêm trường tăng tự động trong tất cả các bảng.

Nếu bạn có một bảng không có khóa rõ ràng, trường tăng tự động có vẻ là một ý tưởng hay. Rốt cuộc, bạn không muốn select * from blog where body = '[10000 character string]'. Bạn muốn select * from blog where id = 42. Tôi tranh luận rằng trong hầu hết các trường hợp này, những gì bạn thực sự muốn là một định danh duy nhất; không phải là một định danh duy nhất tuần tự. Bạn có thể muốn sử dụng một định danh duy nhất phổ quát thay thế.

Có các chức năng trong hầu hết các cơ sở dữ liệu để tạo các định danh duy nhất ngẫu nhiên ( uuidtrong mysql, postgres. newidTrong mssql). Điều này cho phép bạn tạo dữ liệu vào nhiều cơ sở dữ liệu, trên các máy khác nhau, bất cứ lúc nào, không có kết nối mạng giữa chúng và vẫn hợp nhất dữ liệu với xung đột bằng không. Điều này cho phép bạn dễ dàng thiết lập nhiều máy chủ hơn và thậm chí các trung tâm dữ liệu, ví dụ như với microservice.

Điều này cũng tránh những kẻ tấn công đoán url của các trang mà họ không nên truy cập. Nếu có thì https://example.com/user/1263có lẽ https://example.com/user/1262cũng như vậy. Điều này có thể cho phép tự động hóa khai thác bảo mật trong trang hồ sơ người dùng.

Cũng có rất nhiều trường hợp một cột uuid là vô dụng hoặc thậm chí có hại. Giả sử bạn có một mạng xã hội. Có một cái usersbàn và một cái friendsbàn. Bảng bạn bè chứa hai cột userid và trường tăng tự động. Bạn muốn 3làm bạn với 5, vì vậy bạn chèn 3,5vào cơ sở dữ liệu. Cơ sở dữ liệu thêm id tự động tăng và lưu trữ 1,3,5. Bằng cách nào đó, người dùng 3nhấp vào nút "thêm bạn bè" một lần nữa. Bạn chèn 3,5vào cơ sở dữ liệu một lần nữa, cơ sở dữ liệu sẽ thêm id tự động tăng và chèn 2,3,5. Nhưng bây giờ 35là bạn với nhau hai lần! Đó là một sự lãng phí không gian và nếu bạn nghĩ về nó, thì cột tăng tự động cũng vậy. Tất cả bạn cần để xem nếu ablà bạn bè là chọn hàng có hai giá trị đó. Họ là, cùng nhau, một định danh hàng duy nhất. (Bạn có thể muốn viết một số logic để đảm bảo 3,55,3được lặp lại.)

Vẫn có trường hợp id của chuỗi tuần tự có thể hữu ích, như khi xây dựng trình rút gọn url, nhưng chủ yếu (và ngay cả với trình rút gọn url), một id duy nhất được tạo ngẫu nhiên là thứ bạn thực sự muốn sử dụng thay thế.

TL; DR: Sử dụng UUID thay vì tự động tăng, nếu bạn chưa có cách nhận dạng duy nhất cho mỗi hàng.


26
Vấn đề với UUID là chúng chiếm quá nhiều không gian cho phần lớn các bảng. Sử dụng định danh duy nhất đúng cho mỗi bảng.
Stephen

49
Toàn bộ đoạn văn về tính duy nhất là moot - tính duy nhất có thể được thi hành, có hoặc không có khóa chính. Bên cạnh đó, UUID tốt hơn về mặt lý thuyết, nhưng thật tệ khi sử dụng khi gỡ lỗi / thực hiện các nhiệm vụ DBA hoặc làm bất cứ điều gì không "chống lại các cuộc tấn công".

11
Một kịch bản khác khi UUID tốt hơn: triển khai thao tác PUT tạm thời, để bạn có thể thử lại các yêu cầu một cách an toàn mà không cần đưa ra các hàng trùng lặp.
yurez

21
Ở điểm "đoán URL", có một ID duy nhất (tuần tự hoặc theo cách khác) không có nghĩa là phơi bày ID đó cho người dùng ứng dụng.
Dave Sherohman

7
Hoàn toàn từ quan điểm cơ sở dữ liệu, câu trả lời này là hoàn toàn sai. Sử dụng UUID thay vì số nguyên tăng tự động sẽ tăng chỉ số quá nhanh và ảnh hưởng xấu đến hiệu suất và mức tiêu thụ bộ nhớ. Nếu bạn đang nói từ quan điểm của dịch vụ web hoặc ứng dụng web, thì nên có một lớp ở giữa cơ sở dữ liệu và giao diện người dùng. Bất cứ điều gì khác là thiết kế xấu. Sử dụng dữ liệu làm khóa chính thậm chí còn tồi tệ hơn. Các khóa chính chỉ được sử dụng trên lớp dữ liệu, không ở đâu khác.
Mã Drunken Monkey

60

Phím tự động có hầu hết các lợi thế.

Nhưng một số nhược điểm có thể có thể là:

  • Nếu bạn có khóa doanh nghiệp, bạn cũng phải thêm một chỉ mục duy nhất trên (các) cột đó để thực thi các quy tắc kinh doanh.
  • Khi truyền dữ liệu giữa hai cơ sở dữ liệu, đặc biệt là khi dữ liệu nằm trong nhiều bảng (nghĩa là chính / chi tiết), nó không đơn giản vì các chuỗi không được đồng bộ hóa giữa các cơ sở dữ liệu và trước tiên bạn sẽ phải tạo một bảng tương đương bằng cách sử dụng khóa doanh nghiệp khớp với nhau để biết ID nào từ cơ sở dữ liệu gốc tương ứng với ID nào trong cơ sở dữ liệu đích. Tuy nhiên, đó không phải là vấn đề khi chuyển dữ liệu từ / sang các bảng bị cô lập.
  • Nhiều doanh nghiệp có các công cụ báo cáo đặc biệt, đồ họa, điểm và nhấp, kéo và thả. Vì ID tự động là vô nghĩa, loại người dùng này sẽ khó có thể hiểu được dữ liệu bên ngoài "ứng dụng".
  • Nếu bạn vô tình sửa đổi khóa doanh nghiệp, rất có thể bạn sẽ không bao giờ khôi phục được hàng đó vì bạn không còn có thứ gì để con người xác định. Điều đó đã gây ra lỗi trong nền tảng BitCoin một lần .
  • Một số nhà thiết kế thêm ID vào bảng tham gia giữa hai bảng, khi PK đơn giản chỉ bao gồm hai ID nước ngoài. Rõ ràng nếu bảng tham gia nằm giữa ba hoặc nhiều bảng, thì ID tự động có ý nghĩa, nhưng sau đó bạn phải thêm một khóa duy nhất khi áp dụng kết hợp FK để thực thi các quy tắc kinh doanh.

Đây là phần bài viết Wikipedia về những nhược điểm của khóa thay thế.


13
Đổ lỗi lỗ hổng mt.gox trên các khóa thay thế có vẻ khá đáng ngờ. Vấn đề là họ đã bao gồm tất cả các trường trong khóa ghép của chúng, thậm chí các trường có thể thay đổi / dễ uốn.
CodeInChaos

6
Một bất lợi "xã hội" của việc sử dụng các khóa tăng tự động là đôi khi "doanh nghiệp" cho rằng không bao giờ có bất kỳ lỗ hổng nào và yêu cầu phải biết điều gì đã xảy ra với các hàng bị thiếu xảy ra khi chèn không thành công (quay ngược giao dịch).
Rick Ryker

4
Một nhược điểm khác là nếu hệ thống phát triển lớn đến mức bạn phải bảo vệ cơ sở dữ liệu, bạn không còn có thể sử dụng tính năng tự động để tạo ra một khóa duy nhất trên toàn cầu. Khi bạn đạt đến điểm đó, bạn có thể có rất nhiều mã dựa trên giả định đó. Có nhiều cách khác để tạo một mã định danh duy nhất sẽ tiếp tục hoạt động nếu cơ sở dữ liệu bị hủy.
kasperd

1
@Voo Không đảm bảo rằng cơ sở dữ liệu bạn chọn hỗ trợ điều đó. Và cố gắng thực hiện nó một lớp cao hơn cơ sở dữ liệu có nghĩa là bạn mất một số đảm bảo mà SQL sẽ cung cấp cho bạn. Cuối cùng, bất kỳ việc gán ID tập trung nào cũng sẽ làm tăng độ trễ nếu bạn có một hệ thống phân tán.
kasperd

1
@Voo Tất nhiên, bất kể quy mô của hệ thống, người ta không nên đưa ra quá nhiều giả định về bản chất của ID tự động. Nếu bạn chỉ có một cơ sở dữ liệu duy nhất, chúng được gán theo thứ tự, nhưng không có gì đảm bảo chúng được cam kết theo thứ tự. Và có thể có khoảng cách trong chuỗi vì không phải tất cả các giao dịch được cam kết.
kasperd

20

Ngược lại, Không, bạn KHÔNG cần phải luôn có PK AutoInc số.

Nếu bạn phân tích dữ liệu của mình một cách cẩn thận, bạn thường xác định các khóa tự nhiên trong dữ liệu. Đây thường là trường hợp khi dữ liệu có ý nghĩa nội tại đối với doanh nghiệp. Đôi khi các PK là đồ tạo tác từ các hệ thống cổ xưa mà người dùng doanh nghiệp sử dụng làm ngôn ngữ thứ hai để mô tả các thuộc tính của hệ thống của họ. Tôi đã thấy số VIN xe được sử dụng làm khóa chính của bảng "Xe" trong hệ thống quản lý đội xe chẳng hạn.

Tuy nhiên, nó có nguồn gốc, NẾU bạn đã có một định danh duy nhất, hãy sử dụng nó. Đừng tạo khóa chính thứ hai, vô nghĩa; nó lãng phí và có thể gây ra lỗi.

Đôi khi bạn có thể sử dụng PK AutoInc để tạo giá trị có ý nghĩa cho khách hàng, ví dụ Số chính sách. Đặt giá trị bắt đầu cho một cái gì đó hợp lý và áp dụng các quy tắc kinh doanh về số không hàng đầu, v.v ... Đây có lẽ là một cách tiếp cận "tốt nhất của cả hai thế giới".

Khi bạn có số lượng nhỏ các giá trị tương đối tĩnh, hãy sử dụng các giá trị có ý nghĩa với người dùng hệ thống. Tại sao nên sử dụng 1,2,3 khi bạn có thể sử dụng L, C, H trong đó L, H và C đại diện cho Cuộc sống, Xe hơi và Nhà trong bối cảnh "Loại chính sách" bảo hiểm hoặc quay lại ví dụ về VIN, về cách sử dụng "TO "Cho Toyota? Tất cả các xe Toyata đều có số VIN bắt đầu "ĐẾN" Đó là một điều ít người dùng cần nhớ, khiến họ ít có khả năng giới thiệu lỗi lập trình và người dùng và thậm chí có thể là đại diện thay thế có thể sử dụng để mô tả đầy đủ trong báo cáo quản lý giúp báo cáo đơn giản hơn để viết và có thể nhanh hơn để tạo ra.

Một sự phát triển hơn nữa của điều này có lẽ là "một cây cầu quá xa" và tôi thường không khuyên bạn nhưng tôi bao gồm nó để hoàn thiện và bạn có thể tìm thấy một cách sử dụng tốt cho nó. Đó là, sử dụng Mô tả làm Khóa chính. Đối với dữ liệu thay đổi nhanh chóng, đây là một sự gớm ghiếc. Đối với dữ liệu rất tĩnh được báo cáo trên All The Time , có thể không. Chỉ cần đề cập đến nó là nó có thể ngồi đó như một khả năng.

Tôi sử dụng PK AutoInc, tôi chỉ cần tham gia vào bộ não của mình và tìm kiếm các lựa chọn thay thế tốt hơn trước. Nghệ thuật thiết kế cơ sở dữ liệu đang làm cho một cái gì đó có ý nghĩa có thể được truy vấn nhanh chóng. Có quá nhiều tham gia cản trở điều này.

EDIT Một trường hợp quan trọng khác mà bạn không cần PK tự động là trường hợp các bảng biểu thị giao điểm của hai bảng khác. Để gắn bó với sự tương tự xe hơi, A Car có 0..n Phụ kiện, Mỗi phụ kiện có thể được tìm thấy trên nhiều chiếc xe. Vì vậy, để thể hiện điều này Bạn tạo một bảng Car_Accessory chứa PK từ Xe hơi và Phụ kiện và các thông tin liên quan khác về các Ngày liên kết, v.v.

Những gì bạn không (thường) cần là một AutoInc PK trên bàn này - nó sẽ chỉ được truy cập qua ô tô "cho tôi biết phụ kiện nào trên chiếc xe này" hoặc từ Phụ kiện "cho bạn biết xe nào có phụ kiện này"


4
> Tất cả các xe Toyata đều có số VIN bắt đầu "ĐẾN" Điều đó không đúng. Họ bắt đầu với "JT" nếu được sản xuất tại Nhật Bản. Toyotas do người Mỹ chế tạo có số VIN hoàn toàn khác nhau en.wikibooks.org/wiki/ Kẻ
Monty Harder

17
Don't create a second, meaningless primary key; it's wasteful and may cause errors.Tuy nhiên, nếu cách bạn thiết lập tính duy nhất cho một bản ghi là sự kết hợp của 6 cột thì việc tham gia trên tất cả 6 cột mọi lúc sẽ rất dễ xảy ra lỗi. Dữ liệu tự nhiên có PK nhưng bạn nên sử dụng một idcột và ràng buộc duy nhất trên 6 cột đó.
Brad

14
Tôi thừa nhận một số trong những gợi ý này mang lại cho tôi một chút xa. Vâng, thực dụng là tốt, nhưng tôi không thể đếm được tần suất ai đó đã thề sống cuộc đời của đứa con đầu lòng của mình rằng một số thuộc tính ngoài miền sẽ duy trì trong suốt những ngày còn lại. Chà, thường thì nó hoạt động tốt cho đến tuần thứ hai sau khi ra mắt, khi các bản sao đầu tiên xuất hiện. ;) Sử dụng "mô tả" làm PK chỉ là quá xa.
AnoE

2
@Monty, xấu của tôi, bạn nói đúng. Bộ nhớ có thể rơi, đã 20 năm kể từ khi tôi thiết kế hệ thống quản lý đội tàu. Không có số VIN nào không phải là khóa chính :) Tôi đã sử dụng AutoInc Asset_ID IIRC dẫn đến thứ tôi quên. Các bảng là các trình liên kết cho các mối quan hệ nhiều-nhiều nơi bạn liên kết, giả sử, xe hơi với phụ kiện (ví dụ: cửa sổ trời) Nhiều xe hơi có nhiều phụ kiện nên bạn cần một bảng "Car_Accessory" có chứa Car_ID và Phụ kiện_ID nhưng hoàn toàn KHÔNG cần Car_Accesory_ID như một PK tự động.
hủy hoại

7
Thật đáng kinh ngạc khi có rất ít "chìa khóa tự nhiên" bất biến. SSN là gì? Không, họ có thể thay đổi. Thật hiếm, nhưng nó có thể xảy ra. Tên người dùng? Không. Cuối cùng, ai đó sẽ có một lý do kinh doanh hợp lệ để thay đổi. VIN thường là một ví dụ trong sách giáo khoa, nhưng không có nhiều người khác. Ngay cả địa chỉ nhà cũng có thể thay đổi, thay đổi đặt tên đường phố.
Erik Funkenbusch

12

Nhiều bảng đã có một id duy nhất tự nhiên. Không thêm một cột id duy nhất (tự động tăng hoặc khác) vào các bảng này. Sử dụng id duy nhất tự nhiên thay thế. Nếu bạn thêm một id duy nhất khác, về cơ bản bạn có một sự dư thừa (trùng lặp hoặc phụ thuộc) trong dữ liệu của bạn. Điều này đi ngược lại các nguyên tắc bình thường hóa. Một id duy nhất phụ thuộc vào độ chính xác khác. Điều này có nghĩa là chúng phải được giữ đồng bộ hoàn hảo mọi lúc trong mọi hệ thống quản lý các hàng này. Đó chỉ là một điểm yếu khác trong tính toàn vẹn dữ liệu của bạn mà bạn không thực sự muốn quản lý và xác nhận lâu dài.

Hầu hết các bảng ngày nay không thực sự cần tăng hiệu suất rất nhỏ mà một cột id duy nhất bổ sung sẽ cung cấp (và đôi khi nó còn làm giảm hiệu suất). Như một quy tắc chung trong CNTT, tránh dư thừa như bệnh dịch hạch! Chống lại nó ở mọi nơi nó được đề nghị cho bạn. Đó là sự vô cảm. Và chú ý trích dẫn. Mọi thứ nên đơn giản nhất có thể, nhưng không đơn giản. Đừng có hai id duy nhất mà một người sẽ đủ, ngay cả khi người tự nhiên có vẻ ít gọn gàng hơn.


3
Bạn không nên chỉ sử dụng ID "tự nhiên" làm khóa chính nếu chúng được đảm bảo tuyệt đối không bao giờ thay đổi? Chẳng hạn, bạn không nên sử dụng số giấy phép lái xe làm khóa chính, bởi vì nếu một người có bằng lái xe mới, bạn sẽ cần cập nhật không chỉ bảng đó mà bất kỳ bảng nào có khóa ngoại tham chiếu nó!
ekolis

1
Có một số lý do tại sao số giấy phép lái xe không đủ điều kiện là id duy nhất tự nhiên. Đầu tiên, một số trong số chúng có nguồn gốc từ các dữ liệu khác, như ngày sinh và tên. Họ không được đảm bảo duy nhất giữa các tiểu bang. Và lấy ví dụ của bạn, khi một người được cấp lại giấy phép với cùng một số, nhưng có lẽ hết hạn kéo dài, điều gì xảy ra sau đó? Họ có một giấy phép khác nhau với cùng một số. Một id tự nhiên vẫn phải đáp ứng các thuộc tính cơ bản của khóa chính. Số giấy phép lái xe (ít nhất là ở Hoa Kỳ) có một số thiếu sót về vấn đề này.
Brad Thomas

1
OK, tôi đoán tôi đã hiểu nhầm định nghĩa của ID tự nhiên rồi; Tôi nghĩ rằng đó chỉ là một ID được xác định bởi các quy tắc kinh doanh, cho dù nó có thực sự được đảm bảo là bất biến hay không.
ekolis

10

Trên các hệ thống lớn hơn, ID là bộ tăng cường tính nhất quán, hãy sử dụng nó ở hầu hết mọi nơi. Trong ngữ cảnh này, các khóa chính riêng lẻ KHÔNG được đề xuất, chúng đắt ở dòng dưới cùng (đọc tại sao).

Mọi quy tắc đều có một ngoại lệ, do đó bạn có thể không cần ID tự động số nguyên trên các bảng phân tầng được sử dụng để xuất / nhập và trên các bảng một chiều hoặc bảng tạm thời tương tự. Bạn cũng sẽ thích GUID thay vì ID trên các hệ thống phân tán.

Nhiều câu trả lời ở đây cho thấy rằng khóa duy nhất hiện có nên được thực hiện. Ngay cả khi nó có 150 ký tự? Tôi không nghĩ vậy.

Bây giờ quan điểm chính của tôi:

Dường như các đối thủ của ID số nguyên tự động đang nói về cơ sở dữ liệu nhỏ với tối đa 20 bảng. Ở đó họ có thể đủ khả năng tiếp cận cá nhân cho mỗi bảng.

NHƯNG một khi bạn có một ERP với hơn 400 bảng, có ID tự động số nguyên ở bất cứ đâu (trừ các trường hợp được đề cập ở trên) chỉ có ý nghĩa lớn. Bạn không dựa vào các lĩnh vực độc đáo khác ngay cả khi chúng có mặt và được bảo đảm cho tính duy nhất.

  • Bạn được hưởng lợi từ quy ước tiết kiệm thời gian, tiết kiệm công sức, dễ nhớ.
  • Trong hầu hết các trường hợp bạn JOINbảng, mà không cần kiểm tra các phím là gì.
  • Bạn có thể có các thói quen mã phổ quát làm việc với cột tự động số nguyên của bạn.
  • Bạn có thể mở rộng hệ thống của mình bằng các bảng mới hoặc plugin người dùng không lường trước trước chỉ bằng cách tham khảo ID của các bảng hiện có. Họ đã có sẵn từ đầu, không có chi phí để thêm chúng.

Trên các hệ thống lớn hơn, có thể đáng để bỏ qua các lợi ích nhỏ của các khóa chính riêng lẻ đó và luôn sử dụng ID tự động số nguyên trong hầu hết các trường hợp. Sử dụng các trường duy nhất hiện có làm khóa chính có thể tiết kiệm một số byte trên mỗi bản ghi nhưng thời gian lưu trữ hoặc lập chỉ mục bổ sung không gây ra vấn đề gì trong các công cụ cơ sở dữ liệu ngày nay. Trên thực tế, bạn đang mất nhiều tiền và tài nguyên hơn vì lãng phí thời gian của các nhà phát triển / nhà bảo trì. Phần mềm ngày nay nên được tối ưu hóa cho thời gian và công sức của các lập trình viên - cách tiếp cận với ID nhất quán đáp ứng tốt hơn nhiều.


Từ kinh nghiệm cá nhân, tôi hoàn toàn đồng ý với nửa sau câu trả lời của bạn. Bạn sẽ cần các khóa duy nhất trên toàn cầu, ít thường xuyên hơn nhiều so với bạn sẽ cần các chỉ mục nhanh và gọn. Nếu bạn cần, hãy tạo bảng GlobalEntities với ID được tạo tự động và cột UUID. Sau đó, thêm khóa ngoại ExGlobalEntityId vào bảng Khách hàng chẳng hạn. Hoặc sử dụng hàm băm của một số giá trị.
Mã say rượu Khỉ

8

Nó không phải là thực hành tốt để thiết kế thừa. Tức là - không phải là thực hành tốt khi luôn có khóa chính tự động tăng khi không cần thiết.

Chúng ta hãy xem một ví dụ mà không cần thiết.

Bạn có một bảng cho các bài viết. Điều này có một khóa chính int idvà một cột varchar có tên title.

Bạn cũng có một bảng đầy đủ các danh mục bài viết Bộ dữ liệu idchính int, varchar name.

Một hàng trong bảng Bài viết có id5 điểm và title "Cách nấu ngỗng với bơ". Bạn muốn liên kết bài viết đó với các hàng sau trong bảng Danh mục của mình: "Fowl" ( id : 20), "Goose" ( id : 12), "Cooking" ( id : 2), "Butter" (id: 9) .

Bây giờ, bạn có 2 bảng: bài viết và chuyên mục. Làm thế nào để bạn tạo mối quan hệ giữa hai?

Bạn có thể có một bảng có 3 cột: id (khóa chính), article_id (khóa ngoại), category_id (khóa ngoại). Nhưng bây giờ bạn có một cái gì đó như:

| id | a_id | c_id |
| 1 | 5 | 20 |
| 2 | 5 | 12 |
| 3 | 5 | 2 |

Một giải pháp tốt hơn là có một khóa chính được tạo thành từ 2 cột.

| a_id | c_id |
| 5 | 20 |
| 5 | 12 |
| 5 | 2 |

Điều này có thể được thực hiện bằng cách làm:

create table articles_categories (
  article_id bigint,
  category_id bigint,
  primary key (article_id, category_id)
) engine=InnoDB;

Một lý do khác để không sử dụng số nguyên tăng tự động là nếu bạn đang sử dụng UUID cho khóa chính của mình.

UUID là theo định nghĩa duy nhất của chúng, nó hoàn thành điều tương tự như sử dụng các số nguyên duy nhất. Họ cũng có những lợi ích (và khuyết điểm) riêng của họ so với số nguyên. Chẳng hạn, với UUID, bạn biết rằng chuỗi duy nhất bạn đang đề cập đến trỏ đến một bản ghi dữ liệu cụ thể; điều này rất hữu ích trong trường hợp bạn không có 1 cơ sở dữ liệu trung tâm hoặc khi các ứng dụng có khả năng tạo bản ghi dữ liệu ngoại tuyến (sau đó tải chúng lên cơ sở dữ liệu vào một ngày sau đó).

Cuối cùng, bạn không cần phải nghĩ về các khóa chính là một điều. Bạn cần nghĩ về chúng như chức năng mà chúng thực hiện. Tại sao bạn cần khóa chính? Để có thể xác định duy nhất các bộ dữ liệu cụ thể từ một bảng bằng cách sử dụng một trường sẽ không bị thay đổi trong tương lai. Bạn có cần một cột cụ thể được gọi idđể thực hiện việc này không, hoặc bạn có thể căn cứ nhận dạng duy nhất này khỏi dữ liệu khác (không thay đổi) không?


7

Hoặc có những kịch bản mà bạn không muốn thêm một lĩnh vực như vậy?

Chắc chắn rồi.

Trước hết, có những cơ sở dữ liệu không có tự động (ví dụ, Oracle, chắc chắn không phải là một trong những ứng cử viên nhỏ nhất xung quanh). Đây phải là một dấu hiệu đầu tiên rằng không phải ai cũng thích hoặc cần chúng.

Quan trọng hơn, hãy nghĩ về ID thực sự là gì - đó là khóa chính cho dữ liệu của bạn. Nếu bạn có một bảng có khóa chính khác, thì bạn không cần ID và không nên có một bảng. Ví dụ: một bảng (EMPLOYEE_ID, TEAM_ID)(trong đó mỗi nhân viên có thể ở trong một số nhóm đồng thời) có một khóa chính được xác định rõ ràng bao gồm hai ID đó. Thêm một IDcột tự động, cũng là một khóa chính cho bảng này, sẽ không có ý nghĩa gì cả. Bây giờ bạn đang nắm 2 khóa chính xung quanh và từ đầu tiên trong "khóa chính" sẽ cho bạn một gợi ý rằng bạn thực sự chỉ nên có một khóa.


9
(Không phải người dùng Oracle tha thứ cho câu hỏi nhưng) Oracle không sử dụng Sequence giống như cách người khác sử dụng Autoincrement / Identity? Có phải nói rằng Oracle không có kiểu dữ liệu Autoincrement thực sự chỉ là một đối số ngữ nghĩa?
Brad

Chà, đó chỉ là một điểm nhỏ; phần chính là ID đang chạy không phù hợp với mọi bảng, do đó, việc làm quen với việc tự động gõ ID tự động trên mỗi bảng có thể không phải là điều khôn ngoan nhất.
AnoE

không có hai khóa chính, chỉ có một khóa chính và tất cả phần còn lại được gọi là khóa ứng viên nếu chúng cũng có thể đóng vai trò là khóa chính ..
rahul tyagi

7

Tôi thường sử dụng cột "danh tính" (số nguyên tăng tự động) khi xác định các bảng mới cho dữ liệu "tồn tại lâu" (các bản ghi tôi dự kiến ​​sẽ chèn một lần và giữ xung quanh vô thời hạn ngay cả khi chúng kết thúc "xóa logic" bằng cách đặt trường bit ).

Có một vài tình huống tôi có thể nghĩ đến khi bạn không muốn sử dụng chúng, hầu hết trong số đó diễn ra các tình huống trong đó một bảng trên một phiên bản của DB không thể là nguồn có thẩm quyền cho các giá trị ID mới:

  • Khi ID gia tăng sẽ có quá nhiều thông tin cho kẻ tấn công tiềm năng. Việc sử dụng cột nhận dạng cho các dịch vụ dữ liệu "đối mặt với công chúng" khiến bạn dễ bị "Vấn đề xe tăng Đức"; nếu bản ghi id 10234 tồn tại, lý do là bản ghi 10233, 10232, v.v. tồn tại, trở lại ít nhất là bản ghi 10001, và sau đó thật dễ dàng để kiểm tra bản ghi 1001, 101 và 1 để tìm ra cột nhận dạng của bạn bắt đầu từ đâu. Các GUID V4 bao gồm chủ yếu là dữ liệu ngẫu nhiên phá vỡ hành vi gia tăng này theo thiết kế, do đó chỉ vì một GUID tồn tại, GUID được tạo bằng cách tăng hoặc giảm một byte của GUID không nhất thiết tồn tại, khiến kẻ tấn công sử dụng dịch vụ khó hơn để lấy bản ghi đơn lẻ như một công cụ kết xuất. Có các biện pháp bảo mật khác có thể hạn chế truy cập tốt hơn, nhưng điều này giúp.
  • Trong bảng tham chiếu chéo M: M. Đây là một loại gimme nhưng tôi đã thấy nó được thực hiện trước đây. Nếu bạn có mối quan hệ nhiều-nhiều giữa hai bảng trong cơ sở dữ liệu của mình, giải pháp chuyển đến là một bảng tham chiếu chéo chứa các cột khóa ngoại tham chiếu PK của mỗi bảng. PK của bảng này hầu như luôn luôn là một khóa tổng hợp của hai khóa ngoại, để có được hành vi chỉ mục tích hợp và để đảm bảo tính duy nhất của các tham chiếu.
  • Khi bạn có kế hoạch chèn và xóa hàng loạt trên bảng này rất nhiều. Có lẽ nhược điểm lớn nhất đối với các cột định danh là hoopla thêm mà bạn phải trải qua khi thực hiện chèn các hàng từ bảng hoặc truy vấn khác, nơi bạn muốn duy trì các giá trị khóa của bảng gốc. Bạn phải bật "chèn nhận dạng" (tuy nhiên, điều đó đã được thực hiện trong DBMS của bạn), sau đó đảm bảo thủ công các khóa bạn đang chèn là duy nhất và sau đó khi bạn thực hiện xong thao tác nhập, bạn phải đặt bộ đếm nhận dạng trong siêu dữ liệu của bảng đến giá trị tối đa hiện tại. Nếu thao tác này xảy ra rất nhiều trên bảng này, hãy xem xét một sơ đồ PK khác.
  • Đối với bảng phân phối.Các cột danh tính hoạt động rất tốt cho các cơ sở dữ liệu đơn lẻ, các cặp chuyển đổi dự phòng và các tình huống khác trong đó một cá thể cơ sở dữ liệu là cơ quan duy nhất trên toàn bộ lược đồ dữ liệu tại bất kỳ thời điểm nào. Tuy nhiên, chỉ có bạn mới có thể đi và vẫn có một máy tính đủ nhanh. Sao chép hoặc vận chuyển nhật ký giao dịch có thể giúp bạn có thêm các bản sao chỉ đọc, nhưng cũng có giới hạn đối với quy mô của giải pháp đó. Sớm hay muộn bạn sẽ cần hai hoặc nhiều phiên bản máy chủ xử lý việc chèn dữ liệu và sau đó đồng bộ hóa với nhau. Khi tình huống đó xảy ra, bạn sẽ muốn trường GUID thay vì trường tăng dần, bởi vì hầu hết các DBMS đều được cấu hình sẵn để sử dụng một phần GUID mà chúng tạo như một mã định danh cụ thể, sau đó tạo phần còn lại của mã định danh hoặc tăng dần. Trong cả hai trường hợp,
  • Khi bạn phải thực thi tính duy nhất trên nhiều bảng trong DB.Chẳng hạn, phổ biến trong các hệ thống kế toán để quản lý Sổ cái chung (với một hàng cho mỗi tín dụng hoặc ghi nợ của mọi tài khoản đã từng xảy ra, do đó, nó sẽ rất lớn rất nhanh) như một chuỗi các bảng biểu thị một tháng theo lịch / năm. Lượt xem sau đó có thể được tạo để nối chúng lại với nhau để báo cáo. Về mặt logic, đây là tất cả một bảng rất lớn, nhưng việc băm nhỏ nó giúp công việc bảo trì của DB dễ dàng hơn. Tuy nhiên, nó trình bày vấn đề về cách quản lý chèn vào nhiều bảng (cho phép bạn bắt đầu đăng nhập giao dịch trong tháng tiếp theo trong khi vẫn đóng cuối cùng) mà không kết thúc bằng các khóa trùng lặp. Một lần nữa, các GUID thay vì các cột số nguyên nhận dạng là giải pháp tiếp theo, vì DBMS được thiết kế để tạo các cột này theo cách thực sự độc đáo,

Có những cách giải quyết cho phép sử dụng các cột định danh trong những tình huống này, như tôi đã đề cập, nhưng trong hầu hết các cách này, việc nâng cấp từ cột số nhận dạng thành GUID đơn giản hơn và giải quyết vấn đề hoàn toàn hơn.


1
Có những trường hợp bạn vẫn có thể cần ID trong các bảng M: N (sử dụng các cột ID, ID_M, ID_N) vì gắn các thuộc tính vào các phiên bản của mối quan hệ M: N của bạn.
miroxlav

V4 GUIDS không được đảm bảo sử dụng PNRG mạnh về mặt mật mã, do đó bạn thực sự không nên dựa vào nó cho ví dụ đầu tiên của mình (mặc dù nếu công cụ db của bạn hứa hẹn mạnh mẽ hơn, bạn có thể sẽ ổn, nhưng đó không phải là di động). Nếu không, một bài viết lý do tốt.
Voo

1
@miroxlav - Tôi sẽ khẳng định rằng nếu một bảng có đủ siêu dữ liệu bổ sung liên quan đến mối quan hệ mà một PK riêng biệt bên ngoài hai FK là một ý tưởng tốt, thì nó không thực sự là một bảng tham chiếu chéo nữa; đó là thực thể riêng của nó xảy ra để tham chiếu hai người khác.
KeithS

@Voo - Bạn nói đúng, V4 GUID không được đảm bảo là ngẫu nhiên về mật mã, chỉ là duy nhất (giống như tất cả các GUID). Tuy nhiên, số đuôi của máy bay chiến đấu phản lực Mỹ không được tạo ra từ dữ liệu / thuật toán hạt giống ngẫu nhiên theo mật mã. Những gì bạn thực sự tìm kiếm là một miền dân cư thưa thớt; GUID V4 có 112 byte dữ liệu ngẫu nhiên, có khả năng xác định duy nhất các bản ghi 5e33.
KeithS

Đặt con số đó vào viễn cảnh, mỗi người đàn ông, phụ nữ và trẻ em trên hành tinh (tất cả 7 tỷ) có thể có 741 nghìn tỷ điểm dữ liệu được phân loại và ID riêng lẻ trong DB của chúng tôi và chúng tôi vẫn chỉ sử dụng một giá trị GUID trên một tỷ . Dữ liệu lớn, như một ngành công nghiệp toàn cầu, thậm chí không gần với quy mô kiến ​​thức này. Ngay cả khi được đưa ra một mẫu cho thế hệ GUID, vẫn có các nguồn entropy khác có liên quan, như thứ tự dữ liệu đi vào hệ thống và được gán GUID.
KeithS

7

Khóa chính tăng tự động (danh tính) là một ý tưởng tốt ngoại trừ lưu ý rằng nó vô nghĩa bên ngoài bối cảnh của cơ sở dữ liệu và các máy khách ngay lập tức của cơ sở dữ liệu đó. Ví dụ: nếu bạn chuyển và lưu trữ một số dữ liệu trong cơ sở dữ liệu khác, sau đó tiến hành ghi dữ liệu khác nhau vào cả hai bảng cơ sở dữ liệu, id sẽ phân kỳ - tức là dữ liệu có id là 42 trong một cơ sở dữ liệu sẽ nhất thiết phải khớp với dữ liệu với một id là 42 trong khác.

Vì điều này, nếu cần thiết vẫn có thể xác định các hàng duy nhất bên ngoài cơ sở dữ liệu (và thường là như vậy), thì bạn phải có một khóa khác cho mục đích này. Một khóa doanh nghiệp được lựa chọn cẩn thận sẽ làm, nhưng bạn thường sẽ ở một vị trí của một số lượng lớn các cột cần thiết để đảm bảo tính duy nhất. Một kỹ thuật khác là có một cột Id là một khóa chính tăng dần tự động và một cột duy nhất (hướng dẫn) khác là một khóa duy nhất không được phân cụm, nhằm mục đích xác định duy nhất hàng ở bất cứ nơi nào nó tồn tại trên thế giới. Lý do bạn vẫn có khóa tăng tự động trong trường hợp này là vì việc phân cụm và lập chỉ mục khóa tăng tự động hiệu quả hơn so với hướng dẫn.

Một trường hợp mà bạn có thể không muốn khóa tăng tự động sẽ là bảng nhiều-nhiều trong đó khóa chính là hợp chất của các cột Id của hai bảng khác (bạn vẫn có thể có khóa tăng tự động ở đây, nhưng tôi không nhìn thấy điểm của nó).

Một câu hỏi khác là kiểu dữ liệu của khóa tăng tự động. Sử dụng Int32 cung cấp cho bạn phạm vi giá trị lớn nhưng tương đối hạn chế. Cá nhân tôi thường xuyên sử dụng các cột bigint cho Id, để thực tế không bao giờ phải lo lắng về việc hết giá trị.


6

Vì những người khác đã tạo ra trường hợp cho khóa chính tăng dần, tôi sẽ tạo một khóa cho GUID:

  • Nó được đảm bảo là duy nhất
  • Bạn có thể có một chuyến đi ít hơn đến cơ sở dữ liệu cho dữ liệu trong ứng dụng của bạn. (Ví dụ, đối với bảng loại, bạn có thể lưu GUID trong ứng dụng và sử dụng bảng đó để truy xuất bản ghi. Nếu bạn sử dụng danh tính, bạn cần truy vấn cơ sở dữ liệu theo tên và tôi đã thấy nhiều ứng dụng thực hiện việc này để lấy PK và sau đó truy vấn nó một lần nữa để có được các chi tiết đầy đủ).
  • Nó rất hữu ích để ẩn dữ liệu. www.domain.com/Article/2 Cho tôi biết bạn chỉ có hai bài viết trong khi www.domain.com/article/b08a91c5-67fc-449f-8a50-ffdf2403444a không cho tôi biết gì.
  • Bạn có thể hợp nhất các bản ghi từ các cơ sở dữ liệu khác nhau một cách dễ dàng.
  • MSFT sử dụng GUIDS để nhận dạng.

Chỉnh sửa: Điểm trùng lặp


5
-1. GUID / UUID không được đảm bảo là duy nhất và không phải là duy nhất 100%. GUID vẫn có độ dài hữu hạn, vì vậy tại một số điểm bạn có thể gặp rủi ro khi nhận được bản sao, mặc dù điều đó rất khó xảy ra. Quan điểm của bạn về các chuyến đi ít hơn đến cơ sở dữ liệu cũng không hợp lệ - tại sao bạn không thể lưu trữ id chính trong ứng dụng, như bạn có thể với khóa GUID?
Niklas H

2
Jeff Atwood nói điều đó tốt hơn bao giờ hết. blog.codinghorror.com/primary-keys-ids-versus-guids
Logic ba giá trị

Vì sao bạn không thể lưu trữ id chính trong ứng dụng của mình? Bởi vì cơ sở dữ liệu tạo ra nó. Nếu bạn chạy hạt giống của mình trên cơ sở dữ liệu trống, bạn có thể giả sử rằng ID sẽ là 1. Điều gì sẽ xảy ra nếu bạn chạy cùng một tập lệnh trên cơ sở dữ liệu có dữ liệu trong đó? ID sẽ không là 1.
Ba logic giá trị

Bạn không nói gì về việc tạo ID trong ứng dụng - bạn vừa viết "lưu trữ". Nhưng nếu cần phải tạo ID bên ngoài cơ sở dữ liệu, thì có, GUID có thể là câu trả lời.
Niklas H

2
Tôi sẽ thêm họ quy mô tốt hơn. Các cơ sở dữ liệu lớn của NoQuery như Cassandra thậm chí không hỗ trợ các khóa tăng tự động.
Karl Bielefeldt

2

Theo nguyên tắc thiết kế tốt, mỗi bảng nên có một cách đáng tin cậy để xác định duy nhất một hàng. Mặc dù đó là những gì một khóa chính dành cho, nhưng nó không luôn đòi hỏi sự tồn tại của khóa chính. Thêm một khóa chính cho mỗi bảng không phải là một thực tiễn xấu vì nó cung cấp cho nhận dạng hàng duy nhất, nhưng nó có thể không cần thiết.

Để duy trì mối quan hệ đáng tin cậy giữa các hàng của hai hoặc nhiều bảng, bạn cần thực hiện thông qua các khóa ngoại, do đó cần có các khóa chính trong ít nhất một số bảng. Thêm khóa chính vào mỗi bảng sẽ giúp mở rộng thiết kế cơ sở dữ liệu của bạn dễ dàng hơn khi đến lúc thêm các bảng hoặc mối quan hệ mới vào dữ liệu hiện có. Lên kế hoạch trước luôn là một điều tốt.

Là một nguyên tắc cơ bản (có lẽ là quy tắc cứng), giá trị của khóa chính sẽ không bao giờ thay đổi trong suốt vòng đời của hàng. Sẽ là khôn ngoan khi cho rằng bất kỳ dữ liệu kinh doanh nào liên tiếp đều có thể thay đổi trong suốt vòng đời của nó, do đó, bất kỳ dữ liệu kinh doanh nào cũng sẽ là ứng cử viên kém cho khóa chính. Đây là lý do tại sao một cái gì đó trừu tượng như một số nguyên tăng tự động thường là một ý tưởng tốt. Tuy nhiên, số nguyên tự động tăng có những hạn chế của chúng.

Nếu dữ liệu của bạn sẽ chỉ có một cuộc sống trong cơ sở dữ liệu của bạn, số nguyên tự động tăng lên là tốt. Nhưng, như đã được đề cập trong các câu trả lời khác, nếu bạn muốn dữ liệu của mình được chia sẻ, đồng bộ hóa hoặc có một cuộc sống bên ngoài cơ sở dữ liệu của bạn, các số nguyên tự động tăng sẽ tạo ra các khóa chính kém. Một lựa chọn tốt hơn sẽ là một hướng dẫn (còn gọi là "id duy nhất toàn cầu").


2

Câu hỏi và nhiều câu trả lời bỏ lỡ điểm quan trọng là tất cả các khóa tự nhiên cho mỗi bảng chỉ nằm trong lược đồ logic cho cơ sở dữ liệu và tất cả các khóa thay thế cho mỗi bảng chỉ nằm trong lược đồ vật lý cho cơ sở dữ liệu. các câu trả lời khác chỉ thảo luận về lợi ích tương đối của số nguyên so với khóa thay thế GUID, mà không thảo luận về lý do tại sao khóa thay thế được sử dụng đúng cách và khi nào.

BTW: Chúng ta hãy tránh sử dụng khóa chính không xác định và không chính xác . Nó là một tạo phẩm của các mô hình dữ liệu quan hệ trước, lần đầu tiên được chọn (không chính xác) thành mô hình quan hệ, sau đó được các nhà cung cấp RDBMS chọn lại vào miền vật lý. Việc sử dụng nó chỉ phục vụ để gây nhầm lẫn về ngữ nghĩa.

Lưu ý từ mô hình quan hệ rằng, để lược đồ logic cơ sở dữ liệu ở dạng bình thường đầu tiên , mỗi bảng phải có một bộ trường hiển thị người dùng, được gọi là khóa tự nhiên, xác định duy nhất mỗi hàng của bảng. Trong hầu hết các trường hợp, một khóa tự nhiên như vậy đã được xác định dễ dàng, nhưng đôi khi phải xây dựng một khóa, cho dù là trường ngắt kết nối hay không. Tuy nhiên, khóa được xây dựng như vậy vẫn luôn hiển thị cho người dùng và do đó luôn nằm trong lược đồ logic của cơ sở dữ liệu.

Ngược lại, bất kỳ khóa thay thế nào trên bảng đều nằm hoàn toàn trong lược đồ vật lý cho cơ sở dữ liệu (và do đó phải luôn luôn, vì lý do bảo mật và bảo trì tính toàn vẹn của cơ sở dữ liệu, hoàn toàn vô hình đối với người dùng cơ sở dữ liệu). Lý do duy nhất để giới thiệu khóa thay thế là để giải quyết các vấn đề về hiệu năng trong bảo trì vật lý và sử dụng DB; cho dù đó là tham gia, sao chép, nhiều nguồn phần cứng cho dữ liệu hoặc khác.

Vì lý do duy nhất cho việc giới thiệu khóa thay thế là hiệu suất, chúng ta hãy cho rằng chúng ta muốn nó được biểu diễn. Nếu vấn đề về hiệu năng trong tay là tham gia, thì chúng ta nhất thiết muốn làm cho khóa thay thế của chúng ta càng hẹp càng tốt (mà không cản trở phần cứng, do đó, các số nguyên và byte ngắn thường bị loại bỏ). Tham gia hiệu suất dựa trên chiều cao chỉ mục tối thiểu, do đó, số nguyên 4 byte là một giải pháp tự nhiên. Nếu vấn đề về hiệu năng của bạn là tốc độ chèn, số nguyên 4 byte cũng có thể là một giải pháp tự nhiên (tùy thuộc vào nội bộ RDBMS của bạn). Nếu vấn đề về hiệu suất của bạn đối với bảng là sao chép hoặc nhiều nguồn dữ liệu so với một số công nghệ khóa thay thế khác , thì đó là GUID hoặc khóa hai phần (ID máy chủ + số nguyên) có thể phù hợp hơn. Cá nhân tôi không phải là người yêu thích GUID nhưng chúng rất tiện lợi.

Để tổng hợp, không phải tất cả các bảng sẽ yêu cầu khóa thay thế (thuộc bất kỳ loại nào); chúng chỉ nên được sử dụng khi thấy cần thiết cho hiệu suất của bảng đang được xem xét. Bất kể bạn thích công nghệ khóa thay thế nào, hãy suy nghĩ cẩn thận về nhu cầu thực tế của bảng trước khi đưa ra lựa chọn; thay đổi lựa chọn công nghệ khóa thay thế cho một bảng sẽ làm việc mệt mỏi. Tài liệu số liệu hiệu suất chính cho bảng của bạn để người kế nhiệm của bạn sẽ hiểu các lựa chọn được thực hiện.

Trường hợp đặc biệt

  1. Nếu các yêu cầu kinh doanh của bạn bắt buộc đánh số tuần tự các giao dịch cho mục đích kiểm toán (hoặc khác) thì lĩnh vực đó không phải là khóa thay thế; nó là một chìa khóa tự nhiên (có yêu cầu thêm). Từ tài liệu, một số nguyên tăng tự động chỉ tạo ra các khóa thay thế , vì vậy hãy tìm một cơ chế khác để tạo ra nó. Rõ ràng một số loại màn hình sẽ là cần thiết và nếu bạn đang tìm nguồn cung ứng các giao dịch của mình từ nhiều trang web thì một trang web sẽ trở nên đặc biệt , nhờ vào việc là trang chủ lưu trữ được chỉ định cho màn hình.

  2. Nếu bảng của bạn sẽ không bao giờ nhiều hơn khoảng một trăm hàng thì chiều cao chỉ mục là không liên quan; mọi truy cập sẽ được quét bằng bảng. Tuy nhiên, so sánh chuỗi trên chuỗi dài vẫn sẽ đắt hơn nhiều so với so sánh số nguyên 4 byte và đắt hơn so với so sánh GUID.

  3. Một bảng các giá trị mã được khóa bởi trường char (4) phải có hiệu suất như một bảng có số nguyên 4 byte. Mặc dù tôi không có bằng chứng về điều này nhưng tôi sử dụng giả định thường xuyên và chưa bao giờ có lý do để đưa ra.


-1

Không chỉ là nó không thực hành tốt, trên thực tế, nó được mô tả như là một mô hình chống trong cuốn sách Antipotypes của Bill Karwin.

Không phải mọi bảng đều cần một mã giả - một khóa chính có giá trị tùy ý, không phải thứ gì đó có giá trị ngữ nghĩa cho mô hình - và không có lý do gì để luôn gọi nó id.


điều này dường như không cung cấp bất cứ điều gì đáng kể qua các điểm được thực hiện và giải thích trong 9 câu trả lời trước
gnat

2
và tại sao điều này có thể quan trọng?
gnat

3
@gnat Bởi vì đó là một cuốn sách về thực hành tốt nhất, trực tiếp giải quyết câu hỏi. Nó không rõ ràng sao?
Pedro Werneck

3
không phải là nhỏ nhất Google tìm kiếm "cuốn sách thực hành tốt nhất về sql" cho thấy khoảng 900 nghìn liên kết với tôi, tại sao cái này lại đặc biệt xứng đáng
gnat

1
@gnat Tôi sẽ không tranh luận cả ngày. Bạn không thích câu trả lời, đó là những gì downvote dành cho.
Pedro Werneck

-2

Điều này khá phổ biến - nếu không bạn sẽ cần xác thực rằng khóa thực sự là duy nhất. Điều này sẽ được thực hiện bằng cách xem xét tất cả các phím khác ... sẽ tốn thời gian. Có một khóa gia tăng sẽ trở nên đắt đỏ vì số hồ sơ của bạn gần với giá trị tràn khóa.

Tôi thường làm cho các con trỏ rõ ràng hơn tên trường ref_{table}hoặc ý tưởng tương tự.

Nếu không cần thiết phải chỉ ra bên ngoài một bản ghi thì bạn không cần id.


Giá trị tái đầu tư chính?
AJJ

Một số nguyên không dấu có giá trị tối đa là 4294967295 trước khi thêm 1 sẽ cuộn nó thành 0. Hãy nhớ nếu bạn thêm một bản ghi rồi xóa nó, bộ đếm vẫn tăng. Đảm bảo bạn sử dụng unsigned intcho loại trường nếu không giới hạn là một nửa số đó.
Johnny V


2
Nếu bạn thêm / xóa nhiều hàng, bộ đếm tăng tự động cuối cùng sẽ tràn.
Johnny V

1
Làm thế nào để mọi người xử lý rollover? Điều gì xảy ra nếu có các bản ghi có ID thấp không bao giờ bị xóa, nhưng bạn đang bắt đầu gần cuối nơi một số ID nằm ở đầu trên của 4294967295? "Lập chỉ mục lại" có thể được thực hiện?
AJJ

-2

Tôi sẽ không nói nó nên luôn luôn được thực hiện. Tôi đã có một bảng ở đây không có khóa duy nhất - và nó không cần một bảng. Đó là một nhật ký kiểm toán. Sẽ không bao giờ có bản cập nhật, các truy vấn sẽ trả về tất cả các thay đổi đối với nội dung đang được ghi nhưng đó là cách tốt nhất có thể được thực hiện một cách hợp lý, cần một con người để xác định thay đổi sai. (Nếu mã có thể không được phép ở vị trí đầu tiên!)


-3

Một bộ đếm tăng tự động cho khóa chính không phải là một ý tưởng tốt. Đó là bởi vì bạn cần quay lại cơ sở dữ liệu để tìm khóa tiếp theo và tăng thêm một trước khi chèn dữ liệu của bạn.

Điều đó được nói rằng tôi thường sẽ sử dụng bất cứ thứ gì mà cơ sở dữ liệu có thể cung cấp cho khóa chính thay vì sử dụng nó như một phần của ứng dụng.

Bằng cách để cơ sở dữ liệu tự nhiên cung cấp nó cho bạn, nó có thể đảm bảo khóa là duy nhất cho những gì nó cần.

Tất nhiên không phải tất cả các cơ sở dữ liệu đều hỗ trợ nó. Trong trường hợp đó, tôi thường sử dụng bảng lưu trữ các khóa chính và sử dụng phạm vi cao và thấp được quản lý trong ứng dụng. Đây là giải pháp hiệu quả nhất mà tôi tìm thấy bởi vì bạn nhận được phạm vi 10000 số và tự động tăng chúng trên ví dụ ứng dụng. Một trường hợp ứng dụng khác có thể lấy một nhóm số khác để làm việc. Bạn cần một nguyên hàm khóa chính đủ lớn, chẳng hạn như dài 64 bit.

UUID Tôi không sử dụng làm khóa chính vì chi phí xây dựng và lưu trữ chúng cao hơn nhiều so với việc tăng giá trị dài lên một. UUID vẫn đối phó với nghịch lý sinh nhật ở chỗ một bản sao có thể phát sinh về mặt lý thuyết.


3
Số khóa tăng tự động có nghĩa là việc tăng khóa được cơ sở dữ liệu thực hiện tự động. Đôi khi (tôi đang nhìn bạn, Oracle!) Bạn cần kết hợp trình tự + trình kích hoạt để làm như vậy, nhưng bạn không bao giờ cần phải tra cứu giá trị được chèn trước đó cho khóa, thêm 1, sau đó sử dụng nó.
SQB

Với một số khung liên tục như JPA nếu bạn muốn trả về giá trị của khóa, nó đã được tạo lại cho người gọi, bạn cần tải lên bản ghi để xem khóa.
Archimedes Trajano
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.