Guid vs INT - Cái nào tốt hơn làm khóa chính?


97

Tôi đã đọc xung quanh lý do để sử dụng hay không Guidint.

intnhỏ hơn, nhanh hơn, dễ nhớ, giữ một trình tự thời gian. Và như Guid, lợi thế duy nhất tôi tìm thấy là nó là duy nhất. Trong trường hợp nào a Guidsẽ tốt hơn intvà tại sao?

Từ những gì tôi đã thấy, intkhông có sai sót nào ngoại trừ giới hạn số lượng, trong nhiều trường hợp là không liên quan.

Tại sao chính xác được Guidtạo ra? Tôi thực sự nghĩ rằng nó có một mục đích khác ngoài việc dùng làm khóa chính của một bảng đơn giản. (Bất kỳ ví dụ về một ứng dụng thực sự sử dụng Guidcho một cái gì đó?)

Loại (Guid = UniqueIdentifier) ​​trên SQL Server


1
Thay vì chính quan trọng, tôi nghĩ bạn có nghĩa là đại diện chủ chốt tức là một chìa khóa đó không phải là chìa khóa tự nhiên (sau này là chìa khóa chúng tôi sử dụng trong thế giới thực). Có thể bạn có nghĩa là chỉ số cụm.
onedaywhen

Cũng nhớ sự khác biệt giữa KEY (Chính) và INDEX.
Allan S. Hansen


2
" intkhông có sai sót nào ngoại trừ giới hạn số lượng, trong nhiều trường hợp là không liên quan.": thực sự, trong bối cảnh INT vs GUID, giới hạn trên của một chữ ký 32 bit INThoàn toàn không liên quan vì giới hạn trên của một chữ ký , 64-bit BIGINTvượt xa gần như tất cả các lần sử dụng (thậm chí nhiều hơn nếu bạn bắt đầu đánh số ở giới hạn thấp hơn và tương tự như vậy INT) và nó vẫn chỉ bằng một nửa kích thước của GUID (8 byte thay vì 16) và tuần tự.
Solomon Rutzky

Câu trả lời:


89

Điều này đã được hỏi trong Stack Overflow tại đâyđây .

Bài đăng của Jeff giải thích rất nhiều về ưu và nhược điểm của việc sử dụng GUID.

HƯỚNG DẪN

  • Duy nhất trên mọi bảng, mọi cơ sở dữ liệu và mọi máy chủ
  • Cho phép dễ dàng hợp nhất các bản ghi từ các cơ sở dữ liệu khác nhau
  • Cho phép dễ dàng phân phối cơ sở dữ liệu trên nhiều máy chủ
  • Bạn có thể tạo ID ở bất cứ đâu, thay vì phải làm tròn đến cơ sở dữ liệu
  • Hầu hết các kịch bản sao chép đều yêu cầu các cột GUID

Nhược điểm

  • Nó lớn hơn gấp 4 lần so với giá trị chỉ mục 4 byte truyền thống; điều này có thể có tác động nghiêm trọng đến hiệu suất và lưu trữ nếu bạn không cẩn thận
  • Cồng kềnh để gỡ lỗi ( where userid='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')
  • Các GUID được tạo phải được tuần tự một phần để có hiệu suất tốt nhất (ví dụ: newsequentialid()trên SQL Server 2005+) và để cho phép sử dụng các chỉ mục được nhóm

Nếu bạn chắc chắn về hiệu suất và bạn không có kế hoạch sao chép hoặc hợp nhất các bản ghi, sau đó sử dụng intvà đặt nó tự động tăng ( hạt giống nhận dạng trong SQL Server ).


20
Một khía cạnh khác của phương pháp GUID là bạn không thể sử dụng nó làm định danh cho người dùng cuối của mình. Bạn có thực sự mong đợi người dùng của bạn nói với bạn trên điện thoại rằng họ có vấn đề với Đơn hàng "BAE7DF4-DDF-3RG-5TY3E3RF456AS10" không? :)
Brann

3
Nếu bạn không sử dụng các hướng dẫn tuần tự và khóa chính của bạn được phân cụm (SQL Server defaul) thì tất cả các phần chèn dữ liệu của bạn sẽ được phân tán ngẫu nhiên trong bảng, dẫn đến phân mảnh dữ liệu của bạn. Đó là giả định rằng dữ liệu thường sẽ được chèn theo một thứ tự nào đó, chẳng hạn như theo thời gian.
datagod

6
Các hướng dẫn tuần tự chỉ tuần tự cho đến khi phiên bản SQL được khởi động lại. Sau đó, giá trị đầu tiên nhiều khả năng sẽ thấp hơn giá trị trước vì cách tạo ra giá trị gốc, gây ra tất cả các loại vấn đề một lần nữa.
mrdenny

20
@Brann Lý tưởng nhất là bạn sẽ không được cung cấp giá trị PK của mình cho người dùng cuối ngay từ đầu. Tôi biết nó là hơi phổ biến để làm như vậy, và đó là điều mà bản thân tôi đã làm trong quá khứ trước khi tôi học được không. Nhưng vì không nên thực hiện, lý do cụ thể đó để thích INT hơn GUID không phải là lý do hợp lệ.
Solomon Rutzky

2
@ChadKuehn Chọn UNIQUEIDENTIFIERqua INTINTcó một giới hạn trên là lập luận khá nghèo kể từ khi là vô hạn, trong khi đủ sự thật, không phải là một thực tế lợi ích. Bạn có thể dễ dàng tăng gấp đôi công suất hiệu quả của một INTbằng cách bắt đầu ở mức giới hạn thấp hơn (-2,14 tỷ) thay vì ở mức 1. Hoặc, nếu toàn bộ 4,3 tỷ không đủ, thì hãy bắt đầu với BIGINTmức chỉ còn 8 byte là so với 16 cho GUID, và nó là seqeuential.
Solomon Rutzky 7/10/2015

18

Nếu bạn đang đồng bộ hóa dữ liệu của mình với nguồn bên ngoài, GUID liên tục có thể tốt hơn nhiều. Một ví dụ nhanh về việc chúng tôi đang sử dụng GUID là một công cụ được gửi cho khách hàng để thu thập dữ liệu mạng của họ và thực hiện một số lớp khám phá tự động, lưu trữ các bản ghi được tìm thấy và sau đó tất cả các hồ sơ khách hàng được tích hợp vào cơ sở dữ liệu trung tâm trở lại vào kết thúc của chúng tôi. Nếu chúng tôi sử dụng một số nguyên, chúng tôi sẽ có 7.398 "1" và sẽ khó khăn hơn nhiều để theo dõi "1" là số nào.


3
GUID chắc chắn là tốt như các mã định danh bên ngoài và tôi sẽ giữ một chỉ mục không được phân cụm là "khóa ngoài", tôi vẫn sẽ giữ một int là "khóa nội bộ" làm cơ sở cho các mối quan hệ của chỉ mục và khóa ngoài. Nếu một cái gì đó sẽ vượt qua một ranh giới kiến ​​trúc (ví dụ: giao tiếp với một ứng dụng khác) tôi đánh giá cao việc có một cái gì đó không thể trộn lẫn.
Greg

15

Tôi đã sử dụng một phương pháp lai với thành công. Các bảng chứa BOTH một idcột số nguyên khóa chính tự động tăng VÀ một guidcột. Có guidthể được sử dụng khi cần thiết để xác định hàng duy nhất trên toàn cầu và idcó thể được sử dụng cho các truy vấn, sắp xếp và nhận dạng con người của hàng.


3
GUID mang lại giá trị gì nếu con người idđã đủ để xác định một hàng?
Martin Smith

6
Id xác định hàng trong bảng này. GUID (ít nhất là trên lý thuyết) xác định hàng này ở bất cứ đâu trong vũ trụ đã biết. Trong dự án của tôi, mỗi điện thoại di động Android đều có một bản sao giống hệt về cấu trúc của bảng trên cơ sở dữ liệu SQLite cục bộ. Hàng và GUID của nó được tạo trên Android. Sau đó, khi Android được đồng bộ hóa với cơ sở dữ liệu phía sau, hàng cục bộ của nó được ghi vào bảng back-end mà không sợ xung đột với các hàng được tạo từ bất kỳ thiết bị di động Android nào khác.
rmirabelle

2
@MartinSmith Tôi đã sử dụng phương pháp này cho mình và nó hoạt động khá độc đáo. GUID chỉ là một khóa thay thế, với chỉ mục NonClustered và được truyền từ ứng dụng, nhưng chỉ nằm trong bảng chính. Tất cả các bảng liên quan có liên quan thông qua INTPK. Tôi thấy lạ là cách tiếp cận này không phổ biến hơn nhiều vì nó là cách tốt nhất của cả hai thế giới. Có vẻ như hầu hết mọi người chỉ thích giải quyết các vấn đề theo cách rất tuyệt đối, không nhận ra rằng PK không cần phải là GUID để ứng dụng vẫn sử dụng GUID cho tính duy nhất và / hoặc tính di động toàn cầu.
Solomon Rutzky 7/10/2015

1
@rmirabelle Tôi đã nghĩ về cách tiếp cận này và đang do dự, nhưng câu trả lời của bạn đã thuyết phục tôi. Về cơ bản, tôi đang ở trong tình huống tôi cần có một mã định danh duy nhất cho một mục công việc (có thể truy cập mạng từ bất cứ đâu), nhưng trước tiên tôi không muốn đi vòng quanh cơ sở dữ liệu. GUID là một giải pháp tốt cho việc này nhưng tôi tưởng tượng THAM GIA sẽ trở nên chậm hơn nhiều nếu tôi không có khóa cụm liên tiếp.
thay thế

1
@easuter Tôi đồng ý với việc không thêm các trường ID "chỉ vì lợi ích của nó", chẳng hạn như trong các bảng "nhiều cầu" trong đó PK phải là tổng hợp của hai FK có liên quan. Nhưng ở đây, nó không phải là một sự đánh đổi vì trường ID không chỉ đơn thuần là vì lợi ích của nó. Cho phép hệ thống hoạt động hiệu quả là khá quan trọng ;-). VÀ, tôi sẽ lập luận rằng trong trường hợp của bạn, vì GUID được tạo ra bên ngoài, chúng không được bảo đảm là duy nhất, ngay cả khi thực tế chúng là. Nhưng trách nhiệm về tính toàn vẹn dữ liệu là lý do đủ để GUID là khóa thay thế và ID là PK trong trường hợp của bạn :)
Solomon Rutzky

1

Một số thực tiễn tốt nhất hiện có vẫn đề cập rằng bạn nên sử dụng loại dữ liệu có thể chứa ít bộ nhớ hơn trong toàn bộ các giá trị bạn sẽ sử dụng. Chẳng hạn, nếu bạn đang sử dụng nó để lưu trữ số lượng nhà tuyển dụng trong một doanh nghiệp nhỏ và bạn không có khả năng đạt tới 100, thì không ai có thể đề xuất sử dụng giá trị bigint trong khi int (thậm chí là nhỏ) sẽ làm.

Tất nhiên, nhược điểm của việc này giống như "Nói không với khả năng mở rộng!"


Ngoài ra, tôi biết điều này không hoàn toàn liên quan, nhưng có một yếu tố khác liên quan đến điều này. Khi không quá mạnh mẽ, tôi thường cố gắng khuyên bạn nên sử dụng khóa chính không được tạo tự động, nếu nó có ý nghĩa. Ví dụ: nếu bạn đang lưu thông tin của trình điều khiển, đừng bận tâm trong việc tạo cột được tạo tự động mới cho "ID", chỉ cần sử dụng số giấy phép.

Tôi biết điều này nghe có vẻ rất rõ ràng, nhưng tôi thấy rằng bị lãng quên khá thường xuyên.

Đối với ngữ cảnh: phần này của câu trả lời được giải quyết từ cách tiếp cận lý thuyết dữ liệu, trong đó bạn muốn PK của mình là định danh dữ liệu duy nhất cho bản ghi. Hầu hết thời gian chúng ta tạo ra những khi chúng đã tồn tại, do đó câu trả lời trước đó.

Tuy nhiên, rất hiếm khi bạn có thể kiểm soát chặt chẽ các điểm dữ liệu này và do đó, bạn có thể cần phải sửa hoặc điều chỉnh. Bạn không thể làm điều đó với các khóa chính (tốt, bạn có thể, nhưng nó có thể là một nỗi đau).

Cảm ơn @VahiD đã làm rõ.


Không nên sử dụng khóa chính có ý nghĩa, hãy xem xét kịch bản bên dưới, ai đó đã nhập sai số giấy phép và bạn đã sử dụng id này trong 3-4 bảng làm khóa ngoại, làm thế nào để bạn sửa lỗi này? chỉ cần chỉnh sửa số giấy phép là không đủ trong trường hợp này.
VahiD

1
Hài hước: Tôi đã đọc bình luận của bạn và tôi nghĩ "vâng, tất nhiên", sau đó quay lại đọc câu trả lời của tôi và nghĩ rằng "tôi đã nói như vậy"? Thật buồn cười khi mọi thứ thay đổi trong một vài năm. Tôi có lẽ đã đến từ một nền tảng lý thuyết hơn, nhưng trừ khi bạn kiểm soát chặt chẽ nó (hiếm khi) nó không mang lại nhiều lợi ích. Tôi sẽ cập nhật câu trả lời.
Alpha

upvote cho sự phát triển trong những năm :)
VahiD

1

Sử dụng ID gia tăng tự động có thể rò rỉ thông tin về hoạt động kinh doanh của bạn. Nếu bạn đang điều hành một cửa hàng và sử dụng order_idđể xác định công khai việc mua hàng, thì bất kỳ ai cũng có thể tìm ra số lượng bán hàng hàng tháng của bạn bằng số học đơn giản.


0

Một điều nữa với cách GUID được tạo ra. mrdenny đã chỉ ra một cách chính xác rằng ngay cả khi new resultentialid () đang được sử dụng, việc khởi động lại các thể hiện khiến các giá trị mới bắt đầu bằng các "lỗ hổng" bị bỏ lại trong quá trình xử lý trước. Một điều khác ảnh hưởng đến GUID "tuần tự" là card mạng. Nếu tôi nhớ chính xác, UID của NIC được sử dụng như một phần của thuật toán GUID. Nếu một NIC được thay thế, không có gì đảm bảo rằng UID sẽ có giá trị cao hơn để duy trì khía cạnh tuần tự của mọi thứ. Tôi cũng không chắc chắn làm thế nào nhiều NIC có thể ảnh hưởng đến việc gán giá trị bằng thuật toán.

Chỉ là một suy nghĩ và tôi hy vọng tôi đang nhớ chính xác. Có một ngày tuyệt vời!


2
Chào mừng bạn đến với Quản trị viên Cơ sở dữ liệu, bobo8734. Bạn có thể tìm thấy một số nguồn cho những bình luận này? Nếu bạn không chắc chắn về họ, có lẽ họ sẽ được phục vụ tốt hơn như một nhận xét (khi bạn có đại diện cho nó) hơn là một câu trả lời độc lập.
LowlyDBA

-6

Sử dụng cả hai

Sử dụng int / Bigint cho Khóa chính vì nó dễ dàng duy trì và sử dụng làm quan hệ khóa ngoài.

Nhưng liên kết một cột với GUID để mỗi hàng cũng có một cột duy nhất


2
Giải thích lý do của bạn đằng sau đề nghị này sẽ không làm tổn thương bất cứ ai, tôi chắc chắn.
Andriy M

GUID dài 36 ký tự sẽ khó đọc trong trường hợp bạn đang tìm kiếm một trường hợp cụ thể ..
Abdul Hannan Ijaz

1
Được rồi, nhưng điều đó không thực sự giải thích tại sao OP nên sử dụng cả hai intguid, như bạn đang gợi ý trong câu trả lời của mình. Và bên cạnh đó, tôi đã không nói về việc giải thích đề xuất của bạn chỉ với tôi - quan điểm của tôi là bạn có thể muốn cập nhật câu trả lời của mình . Nhân tiện, bạn có biết rằng một người trả lời khác đã đề xuất tương tự (ít nhiều) như bạn không?
Andriy M

Yup tôi có ý tương tự .. BTW tuyệt vời :)
Abdul Hannan Ijaz
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.