Chia sẻ một chuỗi khóa chính duy nhất trên cơ sở dữ liệu?


14

Đây có phải là một cách chấp nhận để sử dụng một chuỗi đơn làm khóa chính trên tất cả các bảng (thay vì một khóa chính là duy nhất cho một bảng nhất định, nó là duy nhất cho tất cả các bảng)? Nếu vậy, nó có khách quan hơn so với việc sử dụng một chuỗi khóa chính duy nhất trên các bảng.

Tôi là một nhà phát triển phần mềm cơ sở, không phải là một DBA, vì vậy tôi vẫn đang học nhiều kiến ​​thức cơ bản về thiết kế cơ sở dữ liệu tốt.

Chỉnh sửa: Trong trường hợp bất kỳ ai thắc mắc, gần đây tôi đã đọc một bài phê bình về thiết kế cơ sở dữ liệu bởi một trong những DBA của công ty chúng tôi đã đề cập rằng đó là một vấn đề mà thiết kế đã không sử dụng một khóa chính duy nhất trên toàn bộ cơ sở dữ liệu, nghe có vẻ khác so với những gì Tôi đã học được cho đến nay.

Edit2: Để trả lời một câu hỏi trong các bình luận, đây là cho Oracle 11g, nhưng tôi đã tự hỏi ở mức độ cụ thể không phải là cơ sở dữ liệu. Nếu câu hỏi này phụ thuộc vào cơ sở dữ liệu, tôi sẽ muốn biết lý do tại sao, nhưng trong trường hợp như vậy tôi sẽ tìm kiếm một câu trả lời cụ thể cho Oracle.


2
Đó thường là một ý tưởng khủng khiếp, vì lý do hiệu suất.
Phil

1
Trên thực tế, có một lợi ích mạnh mẽ hơn khi có mỗi bảng với phạm vi khóa chính độc lập, riêng. Nhưng chỉ ở chỗ khi bạn nhìn vào một loạt ID bạn có thể nói, cái này là Tài khoản, cái đó là Người mua hàng, v.v. Làm điều này đòi hỏi một số thiết lập và (như bất kỳ mục đích đặc biệt nào) chăm sóc và cho ăn liên tục. (Vâng, tôi đã làm việc với một hệ thống như thế này, nhiều năm trước.)
RLF

DBMS nào bạn đang sử dụng? Oracle? Hậu duệ? DB2?
a_horse_with_no_name

1
Có thể bạn giải thích sai ý anh ấy? Có lẽ anh ấy đã không theo nghĩa đen?
JamesRyan

Có phải DBA của công ty thực sự có nghĩa là không có trường khóa chính nào có trong bất kỳ bảng nào không?
Max Vernon

Câu trả lời:


12

Có thể chấp nhận? Chắc chắn rồi. Chung? Không có lợi? Nghi ngờ.

Ở công việc cũ của tôi, chúng tôi đã thừa hưởng một hệ thống nơi họ có trình tạo trình tự trung tâm (đây là hệ thống SQL Server từ lâu SEQUENCEđã được giới thiệu trong SQL Server 2012). Đó thực sự không phải là nút cổ chai hiệu năng và không nên trừ khi bạn tạo ra hàng trăm nghìn giá trị mỗi giây. Nhưng nó làm cho tất cả các mã phức tạp hơn nhiều so với nó, không có lý do chính đáng. Mục đích của thiết kế là đảm bảo rằng nếu một cái gì đó trong hệ thống được gán giá trị ID là 12, thì chỉ có một thứ trong hệ thống có thể có ID 12. Điều này có vẻ khá khó hiểu với tôi và tôi không bao giờ hiểu được. Nếu tôi có một khách hàng với CustomerID = 12, tại sao điều đó ngăn cản tôi đặt hàng với OrderID = 12?

Tôi thấy sự hữu ích của trình tạo chuỗi trung tâm nếu bạn có nhiều hệ thống và bạn đang tạo ID cho một loại thực thể nhất định (giả sử, một khách hàng hoặc một đơn đặt hàng) từ nhiều hệ thống này. Một chuỗi trung tâm có thể loại bỏ các giá trị mới cho nhiều hệ thống mà không bị tắc nghẽn (chỉ là một điểm thất bại) và không sợ hai hệ thống tạo ra cùng một ID.


Nếu bạn phải lựa chọn giữa một cái gì đó như thế này và chỉ sử dụng các định danh duy nhất làm khóa chính, bạn sẽ có một ưu tiên (mặc dù câu trả lời có khả năng là "nó phụ thuộc")? Có vẻ như GUID sẽ giải quyết vấn đề theo cùng một cách, ngoại trừ việc bạn có được triển khai tiêu chuẩn thay vì phải cuộn trình tạo khóa chính tập trung của riêng mình. Rõ ràng, sử dụng một chuỗi trong SQL 2012 sẽ hoàn thành cả hai điều, nhưng giả sử ai đó đang ở phiên bản cũ hơn?
SqlRyan

2
@SqlRyan Tôi cần hiểu lý do tại sao một OrderID phải hoàn toàn khác biệt với một ID khách hàng. Tôi gần như chắc chắn sẽ không sử dụng GUID cho việc này; thiết lập phạm vi IDENTITY có thể tốt hơn (Khách hàng bắt đầu từ 1, Đơn đặt hàng bắt đầu từ 1000000, v.v.) với các cảnh báo được đưa ra khi bạn sắp hết thời gian sử dụng.
Aaron Bertrand

1
@SqlRyan - sử dụng GUID được triển khai kém làm khóa chính được phân cụm có thể gây ra tất cả các loại vấn đề. Như Aaron đã nói, IDENTITY phù hợp với mục đích tốt hơn nhiều.
Max Vernon

Trong một hệ thống trước đây tôi đã thấy sử dụng một chuỗi duy nhất trên toàn bộ cơ sở dữ liệu, điều này được thực hiện để cho phép một khóa ngoại trỏ đến nhiều bảng khác nhau thay vì một bảng duy nhất, để khi bạn nói rằng khóa ngoại của hai hàng khác nhau là 12, bạn biết họ chỉ vào cùng một thứ mà không cần kiểm tra xem cái bàn nào họ có thể chỉ vào. Số 13 trong cùng một cột có khả năng là khóa chính trên một bảng khác. Cá nhân tôi rất khó chịu với phong cách thiết kế đó.
Lawtonfogle

@AaronBertrand Hoặc sử dụng thay thế số nhận dạng số nguyên đơn giản và nối thêm một số mã vào đầu khi đây là những khách hàng phải đối mặt. ví dụ. I1337, C1337 rõ ràng là hóa đơn hoặc khách hàng
JamesRyan

7

Ý tưởng này có giá trị trong một cơ sở dữ liệu rất phức tạp, nơi mọi người có thể vô tình tham gia vào một bảng bằng cách sử dụng cột sai và nhận các hàng không hợp lệ chỉ vì ID INT giống nhau.

Chúng tôi đã chọn để có các GUID tuần tự làm khóa chính của mình để tránh một số cạm bẫy phân mảnh Index của GUID. Đáng buồn là chúng khá lớn.

Máy chủ SQL có thể tạo GUID tuần tự thông qua mặc định gọi hàm newSequentialID (), do đó không có bảng các khóa được cấp để duy trì và không có nút cổ chai chặn.

Điều này đã cung cấp cho chúng tôi ID duy nhất trên toàn bộ cơ sở dữ liệu, trên toàn bộ doanh nghiệp của chúng tôi thực sự vì chúng thực sự độc đáo.

Giá của khóa học là không gian và nó có vấn đề khi bạn cố gắng đưa dữ liệu đến Kho dữ liệu / Khối nơi tốc độ / kích thước được xác định khi sử dụng các khóa Số nguyên nhỏ hơn.

Tôi tin rằng chúng tôi đã tránh được nhiều lỗi trong ứng dụng của mình do sử dụng chúng.


4

Tôi không thể tưởng tượng lý do đằng sau chuỗi đơn trên tất cả các bảng là gì. Tất cả những gì nó làm là tạo ra một nút cổ chai khi tạo ra các giá trị mới.

Bất kể chi phí nhỏ như thế nào để tạo ra các giá trị khóa tuần tự, trình tạo là một tài nguyên duy nhất, quyền truy cập phải được đồng bộ hóa. Càng nhận được nhiều yêu cầu, cơ hội mà một số người yêu cầu sẽ phải chờ đến lượt tại vòi càng cao. Rõ ràng là trình tạo trình tự đơn được chia sẻ giữa tất cả các bảng sẽ được truy cập thường xuyên hơn bởi nhiều khách hàng hơn, do đó tạo ra nhiều sự tranh chấp hơn bất kỳ một trong nhiều trình tạo. Sự tranh chấp có thể trở nên rõ rệt hơn nếu các quy tắc kinh doanh áp đặt các ràng buộc đối với các giá trị được tạo ra, chẳng hạn như không có khoảng trống hoặc trật tự nghiêm ngặt hoặc trong cơ sở dữ liệu cụm.

Ngay cả với trình tạo trình tự hiệu quả nhất cũng sẽ có một khối lượng công việc gây ra sự tranh chấp không thể giải quyết được.


2
Bạn có thể muốn thêm chi tiết về cách nút cổ chai được tạo ra và tại sao đó là một ý tưởng tồi.
Max Vernon

2

mục đích của PrimaryKey trong các bảng Cơ sở dữ liệu chủ yếu là để thực thi tính duy nhất của dữ liệu được coi là duy nhất, bởi vì tất cả các quy trình công việc không thể được bảo đảm và đảm bảo rằng nó sẽ không dẫn đến trùng lặp dữ liệu. Lý do thứ hai là, nhiều lần PK cũng là ứng cử viên chính cho Chỉ mục được nhóm trên bảng để nó cũng tăng khả năng truy xuất dữ liệu khi / nơi các cột này được sử dụng đúng trong truy vấn chọn.

sử dụng số thứ tự làm Khóa chính giống như mọi bảng đều có cột Danh tính và chỉ có cột đó đang được sử dụng trong Chính khóa. có số thứ tự duy nhất trên DB phải có một số cách sử dụng cụ thể nhưng theo quan điểm của Chính, tôi không hiểu lý do. ví dụ, trong một trong những dự án Datwarhouse mà tôi đã làm việc, chúng tôi có Cột được gọi là LoadBatchID và từ ETL để báo cáo 50% tất cả các bảng có cột này nhưng tại một số nơi, nó có ý nghĩa khác. chúng tôi đã sử dụng Proc duy nhất làm trình tạo số để đảm bảo chúng tôi không tìm thấy xung đột và cũng giúp chúng tôi truy ngược lại tệp gốc từ nơi dữ liệu đến từ đâu và những gì xảy ra ở mỗi giai đoạn khác nhau của ETL.


2

Tôi cho rằng một lý do để làm điều đó là nếu tất cả các thực thể được kế thừa từ một số thực thể cha mẹ. Nói ví dụ bạn muốn có thể đưa ra nhận xét về bất kỳ loại thực thể nào:

create table god_entity (
  id bigserial primary key
);

create table some_table (
  id bigint primary key references god_entity(id),
  ...
);

create table some_other_table (
  id bigint primary key references god_entity(id),
  ...
);

create table comment (
  id bigint primary key references god_entity(id),
  ...
);

create table entity_comment (
  entity_id bigint not null references god_entity(id),
  comment_id bigint not null references god_entity(id),

  primary key (entity_id, comment_id)
);

Thông thường điều này không được thực hiện. .

Không biết về các đặc tính hiệu suất.

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.