Điều gì có thể là nhược điểm của việc luôn có một cột số nguyên duy nhất làm khóa chính?


18

Trong một ứng dụng Web tôi đang làm việc, tất cả các hoạt động cơ sở dữ liệu được trừu tượng hóa bằng cách sử dụng một số kho lưu trữ chung được xác định trên Entity Framework ORM.

Tuy nhiên, để có một thiết kế đơn giản cho các kho lưu trữ chung, tất cả các bảng liên quan phải xác định một số nguyên duy nhất ( Int32trong C #, inttrong SQL). Cho đến bây giờ, điều này luôn luôn là PK của bảng và cũng là IDENTITY.

Khóa ngoại được sử dụng nhiều và chúng tham chiếu các cột số nguyên này. Chúng được yêu cầu cho cả tính nhất quán và để tạo các thuộc tính điều hướng bởi ORM.

Lớp ứng dụng thường thực hiện các thao tác sau:

  • tải dữ liệu ban đầu từ bảng (*) -SELECT * FROM table
  • Cập nhật -UPDATE table SET Col1 = Val1 WHERE Id = IdVal
  • Xóa -DELETE FROM table WHERE Id = IdVal
  • Chèn -INSERT INTO table (cols) VALUES (...)

Hoạt động ít thường xuyên hơn:

  • Chèn hàng loạt - BULK INSERT ... into tabletheo sau (*) bởi tất cả tải dữ liệu (để truy xuất số nhận dạng được tạo)
  • Xóa hàng loạt - đây là thao tác xóa bình thường, nhưng "cồng kềnh" theo quan điểm của ORM:DELETE FROM table where OtherThanIdCol = SomeValue
  • Cập nhật hàng loạt - đây là hoạt động cập nhật bình thường, nhưng "cồng kềnh" theo quan điểm của ORM:UPDATE table SET SomeCol = SomeVal WHERE OtherThanIdCol = OtherValue

* tất cả các bảng nhỏ được lưu trữ ở cấp ứng dụng và hầu như tất cả SELECTssẽ không đến được cơ sở dữ liệu. Một mô hình điển hình là tải ban đầu và rất nhiều INSERTs, UPDATEs và DELETEs.

Dựa trên việc sử dụng ứng dụng hiện tại, có rất ít khả năng đạt được 100 triệu bản ghi trong bất kỳ bảng nào.

Câu hỏi: Từ quan điểm của một DBA, có vấn đề đáng kể nào tôi có thể gặp phải khi giới hạn thiết kế bảng này không?

[CHỈNH SỬA]

Sau khi đọc câu trả lời (cảm ơn về phản hồi tuyệt vời) và các bài viết được tham khảo, tôi cảm thấy mình phải thêm chi tiết:

  1. Thông tin cụ thể về ứng dụng hiện tại - Tôi không đề cập đến ứng dụng web hiện tại, vì tôi muốn hiểu liệu mô hình có thể được sử dụng lại cho các ứng dụng khác không. Tuy nhiên, trường hợp cụ thể của tôi là một ứng dụng trích xuất rất nhiều siêu dữ liệu từ DWH. Dữ liệu nguồn khá lộn xộn (không chuẩn hóa theo cách kỳ lạ, có một số điểm không nhất quán, không có định danh tự nhiên trong nhiều trường hợp, v.v.) và ứng dụng của tôi đang tạo ra các thực thể tách biệt rõ ràng. Ngoài ra, nhiều số nhận dạng được tạo ( IDENTITY) được hiển thị để người dùng có thể sử dụng chúng làm khóa doanh nghiệp. Điều này, bên cạnh việc tái cấu trúc mã lớn, không bao gồm việc sử dụng GUID .

  2. "Họ không nên là cách duy nhất để xác định một hàng duy nhất" (Aaron Bertrand ♦) - đó là một lời khuyên rất tốt. Tất cả các bảng của tôi cũng xác định một CONSTRAINT ĐỘC ĐÁO để đảm bảo rằng các bản sao kinh doanh không được phép.

  3. Thiết kế hướng ứng dụng phía trước so với thiết kế hướng cơ sở dữ liệu - lựa chọn thiết kế là do các yếu tố này gây ra

    1. Giới hạn khung thực thể - cho phép nhiều cột PK, nhưng giá trị của chúng không thể được cập nhật

    2. Giới hạn tùy chỉnh - có một khóa số nguyên đơn giản hóa rất nhiều cấu trúc dữ liệu và mã không phải SQL. Ví dụ: tất cả danh sách các giá trị đều có khóa nguyên và giá trị được hiển thị. Quan trọng hơn, nó đảm bảo rằng bất kỳ bảng nào được đánh dấu cho bộ đệm sẽ có thể được đưa vào Unique int key -> valuebản đồ.

  4. Các truy vấn chọn phức tạp - điều này hầu như sẽ không bao giờ xảy ra vì tất cả dữ liệu bảng nhỏ (<20-30K) được lưu trong bộ nhớ ứng dụng ở cấp ứng dụng. Điều này làm cho cuộc sống khó khăn hơn một chút khi viết mã ứng dụng (viết LINQ khó hơn), nhưng cơ sở dữ liệu được đánh đẹp hơn nhiều:

    1. Danh sách lượt xem - sẽ không tạo ra SELECTcác truy vấn khi tải (mọi thứ được lưu trong bộ nhớ cache) hoặc các truy vấn trông như thế này:

      SELECT allcolumns FROM BigTable WHERE filter1 IN (val1, val2) AND filter2 IN (val11, val12)

      Tất cả các giá trị bắt buộc khác được tìm nạp thông qua tra cứu bộ đệm (O (1)), do đó sẽ không có truy vấn phức tạp nào được tạo.

    2. Chỉnh sửa chế độ xem - sẽ tạo ra các SELECTcâu lệnh như thế này:

      SELECT allcolumns FROM BigTable WHERE PKId = value1

(tất cả các bộ lọc và giá trị là ints)


Bạn có thể tìm thấy các bài đăng liên quan này, vì một số khía cạnh logic, vật lý và thực tế được thảo luận liên quan đến việc sử dụng các cột với các giá trị thay thế do hệ thống tạo ra.
MDCCL

Câu trả lời:


19

Khác với không gian đĩa bổ sung (và lần lượt sử dụng bộ nhớ và I / O), thực sự không có bất kỳ tác hại nào khi thêm cột IDENTITY ngay cả vào các bảng không cần một (ví dụ về bảng không cần cột IDENTITY là một bảng nối đơn giản, giống như ánh xạ người dùng đến các quyền của anh ấy / cô ấy).

Tôi chống lại việc mù quáng thêm chúng vào từng bảng trong một bài đăng trên blog từ năm 2010:

Nhưng phím thay thế không có trường hợp sử dụng hợp lệ - chỉ cần cẩn thận không để cho rằng họ đảm bảo tính độc đáo (mà đôi khi lý do tại sao họ được thêm vào - họ không phải là chỉ có cách để nhận ra duy nhất một hàng). Nếu bạn cần sử dụng khung ORM và khung ORM của bạn yêu cầu các khóa số nguyên một cột ngay cả trong trường hợp khi khóa thực của bạn không phải là số nguyên hoặc không phải là một cột hoặc không, hãy đảm bảo rằng bạn xác định các ràng buộc / chỉ mục duy nhất cho các phím thực sự của bạn, quá.


Cảm ơn đã trả lời nhanh chóng. Có, ứng dụng sử dụng ORM (EF). Nó không yêu cầu các khóa cột số nguyên đơn, nhưng tôi đã đưa ra hạn chế này để làm cho một số thao tác chung dễ dàng hơn nhiều (thiết kế khôn ngoan). Ngoài ra, tất cả các bộ đệm ứng dụng lưu trữ mọi thứ trong bản đồ (từ điển) để truy xuất nhanh bằng khóa và khóa phải là duy nhất. Vì, tôi đã chọn ints trên các hướng dẫn, tôi buộc phải sử dụng IDENTITY cho bất kỳ bảng nào tôi chèn vào. Đối với các bảng giá trị cố định, IDENTITY là không bắt buộc.
Alexei

Tôi nghĩ rằng một số trường hợp kêu gọi tránh kiểm tra tính duy nhất trên các khóa tự nhiên tồn tại. Là một người làm việc với dữ liệu GIS, điều khiến tôi chú ý ngay lập tức là nơi khóa tự nhiên chỉ là hình học hoặc hình học cộng với một số khóa ngoại. Nhìn mọi thứ bằng một hình học chính xác sẽ luôn không thực tế, do đó, một ràng buộc duy nhất đối với nó khó có thể giúp được nhiều và có thể có những hạn chế về hiệu suất. Điều tương tự cũng có thể đúng nếu một phần của khóa tự nhiên là một cột văn bản dài. Nhưng tôi đồng ý: bất cứ khi nào thực tế, vâng, nên áp dụng một ràng buộc duy nhất đối với khóa tự nhiên.
jpmc26

13

Từ kinh nghiệm của tôi, lý do chính và áp đảo để sử dụng ID riêng cho mỗi bảng là như sau:

Trong hầu hết mọi trường hợp, khách hàng của tôi đã tuyên thệ máu trong giai đoạn thụ thai rằng một số trường "tự nhiên" bên ngoài XYZBLARGH_IDsẽ tồn tại mãi mãi và sẽ không bao giờ thay đổi đối với một thực thể nhất định và sẽ không bao giờ được sử dụng lại, cuối cùng đã xuất hiện trường hợp Thuộc tính khóa chính đã bị phá vỡ. Nó không hoạt động theo cách đó.

Sau đó, từ quan điểm DBA, những thứ làm cho DB chậm hoặc cồng kềnh chắc chắn không phải là 4 byte (hoặc bất cứ thứ gì) trên mỗi hàng, mà là những thứ như chỉ mục sai hoặc thiếu, sắp xếp lại bảng / chỉ mục bị quên, tham số điều chỉnh RAM / vùng bảng sai , bỏ qua việc sử dụng các biến ràng buộc và như vậy. Những người này có thể làm chậm DB theo các hệ số 10, 100, 10000 ... không phải là một cột ID bổ sung.

Vì vậy, ngay cả khi có một nhược điểm kỹ thuật, có thể đo lường được khi có thêm 32 bit mỗi hàng, vấn đề không phải là bạn có thể tối ưu hóa ID đi hay không, nhưng tại một thời điểm nào đó, ID sẽ cần thiết hơn có khả năng hơn không. Và tôi sẽ không loại bỏ tất cả các lợi ích "mềm" từ lập trường phát triển phần mềm (như ví dụ ORM của bạn hoặc thực tế là nó giúp các nhà phát triển phần mềm dễ dàng hơn khi tất cả các ID theo thiết kế đều có cùng kiểu dữ liệu, v.v.) .

NB: lưu ý rằng bạn không cần ID riêng cho n:mcác bảng kết hợp vì đối với các bảng như vậy, ID của các thực thể được liên kết sẽ tạo thành khóa chính. Một ví dụ mẫu sẽ là một n:mliên kết kỳ lạ cho phép nhiều liên kết giữa hai thực thể vì bất kỳ lý do kỳ quái nào - những người đó sẽ cần cột ID của riêng họ để tạo PK. Có những thư viện ORM không thể xử lý các PK nhiều cột, vì vậy đó sẽ là một lý do để khoan dung với các nhà phát triển, nếu họ phải làm việc với một thư viện như vậy.


2
"Hiệp hội kỳ lạ n: m cho phép nhiều liên kết giữa hai thực thể" RẤT phổ biến trong cuộc sống thực. Ví dụ: một người sở hữu một chiếc ô tô, sau đó các yêu cầu thay đổi thành thu hồi khi quyền sở hữu bắt đầu và kết thúc, (Một người có thể bán một chiếc xe hơi và mua lại sau đó, và làm hỏng phần mềm của bạn ....)
Ian Ringrose

Yup, một cái gì đó như thế, @IanRingrose.
AnoE

6

Nếu bạn luôn luôn thêm một cột bổ sung vô nghĩa vào mỗi bảng và chỉ tham chiếu các cột đó dưới dạng khóa ngoại thì chắc chắn bạn sẽ làm cho cơ sở dữ liệu trở nên phức tạp và khó sử dụng hơn. Thực tế, bạn sẽ xóa dữ liệu mà người dùng quan tâm khỏi các thuộc tính khóa ngoài và buộc người dùng / ứng dụng phải tham gia thêm để truy xuất thông tin tương tự. Các truy vấn trở nên phức tạp hơn, công việc của trình tối ưu hóa trở nên khó khăn hơn và hiệu suất có thể bị ảnh hưởng.

Các bảng của bạn sẽ có nhiều dữ liệu "thực" hơn so với trước đây. Do đó, cơ sở dữ liệu sẽ khó hiểu và xác minh hơn. Bạn cũng có thể thấy khó hoặc không thể thực thi một số ràng buộc hữu ích nhất định (trong đó các ràng buộc sẽ liên quan đến nhiều thuộc tính không còn trong cùng một bảng).

Tôi khuyên bạn nên chọn khóa cẩn thận hơn và biến chúng thành số nguyên chỉ khi / khi bạn có lý do chính đáng. Dựa trên cơ sở dữ liệu của bạn dựa trên phân tích tốt, tính toàn vẹn dữ liệu, tính thực tế và kết quả có thể kiểm chứng thay vì dựa vào các quy tắc giáo điều.


1
Tuy nhiên, nhiều hệ thống có các khóa chính số nguyên tổng hợp trên mỗi bảng (ví dụ như hầu hết mọi ứng dụng Ruby on Rails từng được viết) mà không gặp phải vấn đề như vậy. Họ cũng không bao giờ gặp phải vấn đề phải thay đổi các khóa chính (điều không bao giờ xảy ra) đối với tất cả các bảng khóa ngoại.
David Aldridge

2
Câu hỏi yêu cầu cho những bất lợi có thể, do đó câu trả lời của tôi. Tôi không phủ nhận rằng các khóa thay thế có thể có ý nghĩa nếu được sử dụng một cách khôn ngoan. Nhưng tôi đã thấy các bảng có 3,4,5 (hoặc nhiều hơn) các khóa ngoại vô nghĩa do đó yêu cầu 3,4,5 hoặc nhiều hơn tham gia để có được kết quả hữu ích từ chúng. Một thiết kế thực dụng hơn có thể không cần phải tham gia.
nvogel

1
Tôi không tin rằng việc thực hiện các truy vấn như vậy là vấn đề chính mà mọi người gặp phải với thiết kế như vậy - đó là việc viết truy vấn mà họ thường phản đối.
David Aldridge

5

Theo kinh nghiệm của tôi với các cơ sở dữ liệu khác nhau, khóa chính Integer luôn tốt hơn các ứng dụng có không có khóa nào được xác định. Hoặc có các khóa tham gia nửa tá cột varar theo những cách vụng về không hợp lý ... (thở dài)

Tôi đã thấy các ứng dụng chuyển từ PK số nguyên sang GUID. Lý do của họ để làm như vậy là vì cần phải hợp nhất dữ liệu từ nhiều cơ sở dữ liệu nguồn trong một số trường hợp nhất định. Các nhà phát triển đã chuyển đổi tất cả các khóa thành GUID để việc hợp nhất có thể xảy ra mà không sợ xung đột dữ liệu, ngay cả trên các bảng không phải là một phần của hợp nhất (chỉ trong trường hợp các bảng đó trở thành một phần của hợp nhất trong tương lai).

Tôi muốn nói rằng một PK số nguyên sẽ không cắn bạn trừ khi bạn có kế hoạch hợp nhất dữ liệu từ các nguồn riêng biệt hoặc bạn có thể có dữ liệu vượt quá giới hạn kích thước số nguyên của mình - tất cả đều thú vị và trò chơi cho đến khi bạn hết dung lượng để chèn .

Tuy nhiên, tôi sẽ nói rằng có thể có ý nghĩa khi đặt chỉ mục được nhóm của bạn trên một cột khác với PK của bạn, nếu bảng sẽ được truy vấn thường xuyên hơn theo cách đó. Nhưng đó là trường hợp ngoại lệ, đặc biệt nếu phần lớn các bản cập nhật và lựa chọn dựa trên các giá trị PK.


2
Âm thanh như một lời biện minh khủng khiếp để thay đổi tất cả các phím để hướng dẫn. Tôi hiện đang làm việc với một cơ sở dữ liệu sử dụng các hướng dẫn cho tất cả các khóa thay thế .. nó không thú vị.
Andy

2
Không. Sử dụng GUID không vui. Tôi không thích chúng, nhưng tôi tôn trọng giá trị của chúng trong một số trường hợp sử dụng nhất định.
CaM

2

Đặt sang một bên:

  • Các cuộc chiến tôn giáo (google thay thế so với khóa tự nhiên)
  • Vấn đề riêng biệt về các chỉ mục được nhóm để xác định trên các bảng của bạn
  • Khả năng lưu trữ tất cả dữ liệu của bạn

Với điều kiện bạn đang sử dụng xóa / cập nhật hàng loạt khi thích hợp và có các chỉ mục để hỗ trợ các hoạt động đó, tôi không nghĩ bạn sẽ gặp rắc rối do tiêu chuẩn PK bạn sử dụng.
Có thể là nếu sau này bạn có EF tạo truy vấn với các liên kết, v.v., thì chúng sẽ không hiệu quả như với kho lưu trữ dựa trên khóa tự nhiên, nhưng tôi không biết đủ về khu vực đó để nói chắc chắn.


4
Tôi không thể nghĩ về một trường hợp trong đó một phép nối trên khóa tự nhiên sẽ hiệu quả hơn một phép nối trên một số nguyên - không nhiều khóa tự nhiên có thể nhỏ hơn 4 byte và nếu có, thì không thể có đủ duy nhất hàng để làm cho vật liệu khác biệt.
Aaron Bertrand

Đối với SQL có thẩm quyền, có thể tối ưu hóa, tôi đồng ý, nhưng tôi đã đề cập đến những hạn chế có thể có của các trình tạo SQL. Kinh nghiệm duy nhất của tôi trong lĩnh vực này là được yêu cầu tạo ra các chế độ xem rộng rãi mà EF có thể được cho ăn bằng thìa - mặc dù có thể các nhà phát triển .net không biết đủ về EF, hoặc có những lý do khác.
TH

@AaronBertrand Tôi sẽ nói rằng cách duy nhất để họ có thể hiệu quả hơn là nếu không cần phải tham gia. Nơi duy nhất tôi xem xét việc sử dụng khóa tự nhiên là với danh sách mã tiêu chuẩn, chẳng hạn như mã tiền tệ ISO4127 (có thể nhận dạng được con người) và tôi có thể sử dụng GBP, EUR, v.v. làm khóa ngoại cho khóa chính hoặc khóa thay thế cho mã tiền tệ bàn.
David Aldridge

@David Tất nhiên, tôi đã nói về những trường hợp cần tham gia. Có rất nhiều trường hợp tôi không muốn khóa tự nhiên tăng sinh trong tất cả các bảng có liên quan, bởi vì các khóa tự nhiên có thể thay đổi, và đó là một điều đau đớn.
Aaron Bertrand

Hmmm, tôi thấy làm thế nào câu trả lời của tôi có thể bị hiểu nhầm là thúc đẩy các khóa ngoại tự nhiên hơn thay thế. Để rõ ràng, tôi thực sự chỉ đề cập đến chúng vì a) Tôi đã đọc câu hỏi của Alexei là "đó có phải là vấn đề chúng ta không sử dụng khóa tự nhiên không?", B) Câu hỏi tóm tắt của Alexei bắt đầu bằng "từ quan điểm của DBA" và tôi cảm thấy tôi nên thừa nhận có nhiều hơn một quan điểm và c) bởi vì tôi nghĩ rằng các tính năng ORM được sử dụng phần lớn chỉ ra sự lựa chọn (nếu nó thực sự có thể tạo ra sự khác biệt). Bản thân tôi chắc chắn trong trại khóa ngoại quốc.
TH

2

Bạn có một vài yếu tố để giúp hướng dẫn bạn,

  1. Định nghĩa và thông số kỹ thuật.

    Nếu một cái gì đó được xác định là duy nhất bởi nhiệm vụ hoặc các định luật vật lý, bạn đang lãng phí thời gian của mình với một khóa thay thế.

  2. Độc đáo.

    Đối với sự tỉnh táo cá nhân, tham gia và chức năng cơ sở dữ liệu cấp cao hơn, bạn sẽ cần, (a) cột duy nhất, (b) chuỗi cột duy nhất

    Tất cả các lược đồ đủ chuẩn hóa (1NF) cung cấp một trong những điều sau đây. Nếu họ không, bạn nên luôn luôn tạo ra một. Nếu bạn có một danh sách những người được thiết lập vào Chủ nhật tình nguyện, và nó bao gồm họ và tên, bạn sẽ muốn biết khi nào bạn có hai Joe Bobs.

  3. Thực hiện và tối ưu hóa.

    Một int có xu hướng là một dạng dữ liệu nhỏ, nhanh để so sánh và bình đẳng. So sánh với chuỗi Unicode có đối chiếu có thể phụ thuộc vào ngôn ngữ (vị trí và ngôn ngữ). Lưu trữ 4242 trong chuỗi ASCII / UTF8 là 4 byte. Lưu trữ nó như một số nguyên, nó phù hợp với 2 byte.

Vì vậy, khi nói đến nhược điểm, bạn có một vài yếu tố.

  1. Nhầm lẫn và mơ hồ.

    1. Mục blog @Aaron Bertrand tổng hợp điều này tốt. Đó không phải là tài liệu để có một OrderID theo đặc tả và tác vụ, và sau đó áp đặt " OrderID " thông qua triển khai cơ sở dữ liệu. Đôi khi bạn phải làm rõ điều đó hoặc tạo một quy ước nhưng điều này có khả năng thêm sự nhầm lẫn.
  2. Không gian.

    Số nguyên vẫn thêm không gian cho hàng. Và, nếu bạn không sử dụng chúng thì không có mục đích.

  3. Phân cụm.

    Bạn chỉ có thể đặt dữ liệu của bạn một cách. Nếu bạn áp đặt khóa thay thế không cần thiết, bạn có phân cụm theo cách đó hoặc theo cách của khóa tự nhiên không?


Đẹp và ngắn ưu & nhược điểm.
Alexei

@Alexei cảm ơn, hãy xem xét đánh dấu nó là đã chọn nếu nó đáp ứng những gì bạn đang tìm kiếm. Hoặc, yêu cầu làm rõ.
Evan Carroll
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.