Chuỗi là khóa chính trong cơ sở dữ liệu SQL


178

Tôi không quen thuộc lắm với cơ sở dữ liệu và các lý thuyết đằng sau cách chúng hoạt động. Có chậm hơn từ quan điểm hiệu suất (chèn / cập nhật / truy vấn) để sử dụng Chuỗi cho Khóa chính so với số nguyên không?

Câu trả lời:


191

Về mặt kỹ thuật là có, nhưng nếu một chuỗi có ý nghĩa là khóa chính thì có lẽ bạn nên sử dụng nó. Tất cả điều này phụ thuộc vào kích thước của bảng bạn đang tạo và độ dài của chuỗi sẽ là khóa chính (chuỗi dài hơn == khó so sánh hơn). Tôi không nhất thiết phải sử dụng một chuỗi cho một bảng có hàng triệu hàng, nhưng mức độ làm chậm hiệu suất mà bạn sẽ nhận được bằng cách sử dụng một chuỗi trên các bảng nhỏ hơn sẽ gây ra những cơn đau đầu mà bạn có thể có bằng một số nguyên không có 't có nghĩa là bất cứ điều gì liên quan đến dữ liệu.


11
Nó sẽ không phụ thuộc vào cơ sở dữ liệu? Tôi có thể nghĩ rằng một chuỗi được lập chỉ mục đúng sẽ không chậm hơn nhiều nếu tất cả từ một số?
Ryan Guill

2
Tôi đồng ý có rất nhiều biến để xem xét. (Trong sqlserver) chúng tôi đã thấy các vấn đề hiệu suất thực sự với việc sử dụng các chuỗi có độ dài ở độ tuổi từ trung bình đến cao và cao hơn ngay cả khi được lập chỉ mục. Mua đúng bạn có những thứ để khắc phục phần cứng này chẳng hạn.
kemiller2002

1
Đủ công bằng. Tôi sẽ đồng ý rằng nếu một chuỗi có ý nghĩa, đó là những gì bạn nên sử dụng. Tôi cũng sẽ nói rằng chắc chắn có thời gian cho các trường GUID hoặc UUID trong cơ sở dữ liệu nơi trường tự động không hoạt động.
Ryan Guill

7
Ngoài ra, hãy nhớ rằng thường có sự khác biệt rất lớn giữa CHAR và VARCHAR khi thực hiện so sánh chỉ số
Tom H

7
Số lượng ý kiến ​​của câu trả lời này cho thấy rõ nó không đầy đủ như thế nào. Đề cập đến lập chỉ mục sẽ là câu trả lời tối thiểu chấp nhận được.
Pedro Rolo

74

Một vấn đề khác khi sử dụng Chuỗi làm khóa chính là vì chỉ mục liên tục được sắp xếp theo thứ tự, khi một khóa mới được tạo sẽ ở giữa thứ tự, chỉ mục phải được xác định lại ... nếu bạn sử dụng tự động số nguyên, khóa mới chỉ được thêm vào cuối chỉ mục.


2
Điều này có thể gây ra "điểm nóng" cho các chèn mới. Miễn là bạn đang quản lý cơ sở dữ liệu của mình đúng cách, bạn nên có thêm dung lượng trên các trang của mình để chèn và dù sao thì việc chia trang sẽ rất hiếm.
Tom H

20
đó là khi các khóa chính được nhóm lại. bạn có thể tạo chúng không bao gồm quá.
Học

Các XID được đặt hàng có thể giúp ích nếu bạn chỉ sử dụng các chuỗi
xid

22

Chèn vào bảng có chỉ mục được nhóm trong đó việc chèn xảy ra ở giữa chuỗi KHÔNG làm cho chỉ mục được viết lại. Nó không làm cho các trang chứa dữ liệu được viết lại. Nếu có chỗ trên trang nơi hàng sẽ đi, thì nó được đặt trong trang đó. Trang đơn sẽ được định dạng lại để đặt hàng vào đúng vị trí trong trang. Khi trang đầy, việc phân chia trang sẽ xảy ra, với một nửa số hàng trên trang sẽ chuyển sang một trang và một nửa sẽ ở trang kia. Các trang sau đó được đưa vào danh sách các trang được liên kết bao gồm dữ liệu bảng có chỉ mục được nhóm. Nhiều nhất, bạn sẽ kết thúc việc viết 2 trang cơ sở dữ liệu.


Lời giải thích hay. Nhưng điều này có đúng với tất cả các cơ sở dữ liệu SQL không? Tôi đã nghe nói về các vấn đề về hiệu suất của MySQL khi sử dụng UUID ngẫu nhiên làm khóa chính.
hgoebl

13

Các chuỗi chậm hơn trong các phép nối và trong cuộc sống thực, chúng rất hiếm khi thực sự độc đáo (ngay cả khi chúng được cho là). Ưu điểm duy nhất là họ có thể giảm số lượng tham gia nếu bạn tham gia vào bảng chính chỉ để lấy tên. Tuy nhiên, các chuỗi cũng thường có thể thay đổi, do đó tạo ra vấn đề phải sửa tất cả các hồ sơ liên quan khi tên công ty thay đổi hoặc người kết hôn. Đây có thể là một thành công lớn và nếu tất cả các bảng có liên quan bằng cách nào đó không liên quan (điều này xảy ra thường xuyên hơn bạn nghĩ), thì bạn cũng có thể có sự không khớp dữ liệu. Một số nguyên sẽ không bao giờ thay đổi trong suốt vòng đời của bản ghi là sự lựa chọn an toàn hơn nhiều từ quan điểm toàn vẹn dữ liệu cũng như từ quan điểm hiệu suất. Khóa tự nhiên thường không tốt cho việc bảo trì dữ liệu.

Tôi cũng muốn chỉ ra rằng điều tốt nhất của cả hai thế giới thường là sử dụng khóa tự động (hoặc trong một số trường hợp chuyên biệt, GUID) làm PK và sau đó đặt một chỉ mục duy nhất vào khóa tự nhiên. Bạn nhận được các liên kết nhanh hơn, bạn không nhận được các bản ghi trùng lặp và bạn không phải cập nhật một triệu hồ sơ con vì tên công ty đã thay đổi.


26
Các chuỗi là ứng cử viên tốt cho PK không có bản sao - nếu không, chúng sẽ không phải là ứng cử viên tốt cho PK. Hãy nghĩ về mã ICD-9, mã quốc gia, số VIN. Sử dụng tên như một ví dụ về một vấn đề với các khóa tự nhiên là sai lầm, bởi vì họ không bao giờ nên là một ứng cử viên ngay từ đầu.
Tom H

6
@Tom H: Mã quận ISO thay đổi. [ en.wikipedia.org/wiki/ISO_3166-1#Editions_and_changes ] Như một câu trả lời cho một câu hỏi liên quan đã nói [ stackoverflow.com/questions/925266/ .] "Đối với PRIMARY KEY, hãy đảm bảo tính duy nhất của chúng nằm trong tầm kiểm soát của bạn"
Steve Schnepp

4
@SteveSchnepp: có và ISO là cơ quan đáng tin cậy để quản lý thay đổi đó. Mặt khác, khi bạn cần hợp nhất chuỗi đơn trị tăng giá trị số nguyên của mình với người khác, bạn sẽ tự mình;)
onedaywhen

1
Tôi đồng ý rằng những cái tên không được coi là một chìa khóa, tôi đã từng thấy đến lúc nào đó.
HLGEM

1
@encedaywhen hợp nhất 2 chuỗi số nguyên tăng dần khá dễ dàng được thực hiện thông qua tiền tố hoặc hậu tố :)
Steve Schnepp

6

Không có vấn đề gì khi bạn sử dụng làm khóa chính miễn là nó ĐỘC ĐÁO. Nếu bạn quan tâm đến tốc độ hoặc thiết kế cơ sở dữ liệu tốt, hãy sử dụng int trừ khi bạn có kế hoạch sao chép dữ liệu, sau đó sử dụng GUID.

Nếu đây là một cơ sở dữ liệu truy cập hoặc một số ứng dụng nhỏ thì ai thực sự quan tâm. Tôi nghĩ lý do tại sao hầu hết các nhà phát triển của chúng tôi tát int hoặc hướng dẫn cũ ở phía trước là vì các dự án có cách phát triển trên chúng tôi và bạn muốn để lại cho mình tùy chọn để phát triển.


5

Quá nhiều biến số. Nó phụ thuộc vào kích thước của bảng, chỉ mục, tính chất của miền khóa chuỗi ...

Thông thường , số nguyên sẽ nhanh hơn. Nhưng sự khác biệt sẽ đủ lớn để quan tâm? Khó mà nói ra được.

Ngoài ra, động lực của bạn để chọn chuỗi là gì? Các phím tăng tự động số thường cũng dễ dàng hơn rất nhiều . Có phải là ngữ nghĩa? Tiện? Nhân rộng / ngắt kết nối mối quan tâm? Câu trả lời của bạn ở đây có thể giới hạn các lựa chọn của bạn. Điều này cũng mang đến cho bạn một tùy chọn "lai" thứ ba mà bạn đang quên: Hướng dẫn.


Điều đó không có ý nghĩa cloutierm, ý bạn là gì?
HLGEM

@HLGEM: Nếu tôi hiểu anh ấy viết, anh ấy có nghĩa là đồng bộ hóa các bản ghi được tạo trên máy tính xách tay với db chính.
Joel Coehoorn

Ý tôi là tôi có hai cơ sở dữ liệu riêng biệt với cùng một thực thể, chỉ có một cơ sở được cập nhật ít thường xuyên hơn cho mục đích lưu trữ liên tục. Nếu tôi Truy vấn thực thể "California" trên Cơ sở dữ liệu A, tôi muốn nó về cơ bản giống với "California" trên Cơ sở dữ liệu B.
chuỗi chính

1
Và nó giống như các bản ghi được đồng bộ hóa được tạo trong máy tính xách tay ở chỗ nó giống nhau: các bản ghi được tạo ở một nơi không nên xung đột với các bản ghi được tạo ở nơi khác. Một giải pháp khả thi ở đây là các phím Guid.
Joel Coehoorn

5

Đừng lo lắng về hiệu suất cho đến khi bạn có một thiết kế đơn giản và hợp lý, phù hợp với chủ đề mà dữ liệu mô tả và phù hợp với mục đích sử dụng dữ liệu. Sau đó, nếu vấn đề về hiệu năng xuất hiện, bạn có thể giải quyết chúng bằng cách điều chỉnh hệ thống.

Trong trường hợp này, hầu như luôn luôn tốt hơn khi đi với một chuỗi như một khóa chính tự nhiên, miễn là bạn có thể tin tưởng nó. Đừng lo lắng nếu đó là một chuỗi, miễn là chuỗi đó ngắn một cách hợp lý, hãy nói tối đa khoảng 25 ký tự. Bạn sẽ không phải trả giá đắt về hiệu suất.

Do người nhập dữ liệu hoặc nguồn dữ liệu tự động luôn cung cấp giá trị cho khóa tự nhiên được cho là hoặc đôi khi bị bỏ qua? Có đôi khi sai trong dữ liệu đầu vào? Nếu vậy, lỗi được phát hiện và sửa chữa như thế nào?

Có phải các lập trình viên và người dùng tương tác chỉ định các truy vấn có thể sử dụng khóa tự nhiên để có được những gì họ muốn không?

Nếu bạn không thể tin tưởng vào khóa tự nhiên, hãy phát minh ra một người thay thế. Nếu bạn phát minh ra một đại diện thay thế, bạn cũng có thể phát minh ra một số nguyên. Sau đó, bạn phải lo lắng về việc che giấu người thay thế khỏi cộng đồng người dùng. Một số nhà phát triển đã không che giấu khóa thay thế đã hối tiếc.


3

Chỉ số ngụ ý rất nhiều so sánh.

Thông thường, các chuỗi dài hơn số nguyên và quy tắc đối chiếu có thể được áp dụng để so sánh, do đó, việc so sánh các chuỗi thường là nhiệm vụ chuyên sâu tính toán hơn so với so sánh các số nguyên.

Tuy nhiên, đôi khi, sử dụng chuỗi làm khóa chính nhanh hơn so với thực hiện nối thêm với string to numerical idbảng.


2

Có, nhưng trừ khi bạn mong đợi có hàng triệu hàng, không sử dụng khóa dựa trên chuỗi vì chậm hơn thường là "tối ưu hóa sớm". Xét cho cùng, các chuỗi được lưu trữ dưới dạng số lớn trong khi các khóa số thường được lưu trữ dưới dạng số nhỏ hơn.

Tuy nhiên, một điều cần chú ý là nếu bạn có các chỉ mục cụm trên bất kỳ khóa nào và đang thực hiện một số lượng lớn các phần chèn không tuần tự trong chỉ mục. Mỗi dòng viết sẽ khiến chỉ mục viết lại. nếu bạn đang thực hiện chèn hàng loạt, điều này thực sự có thể làm chậm quá trình.


2

Hai lý do để sử dụng số nguyên cho các cột PK:

  1. Chúng tôi có thể đặt danh tính cho trường số nguyên tăng tự động.

  2. Khi chúng ta tạo PK, db tạo một chỉ mục (Cluster hoặc Non Cluster) để sắp xếp dữ liệu trước khi nó được lưu trữ trong bảng. Bằng cách sử dụng danh tính trên PK, trình tối ưu hóa không cần kiểm tra thứ tự sắp xếp trước khi lưu bản ghi. Điều này cải thiện hiệu suất trên các bảng lớn.


1

Lý do của bạn để có một chuỗi là khóa chính là gì?

Tôi sẽ chỉ đặt khóa chính thành trường số nguyên tăng tự động và đặt một chỉ mục trên trường chuỗi.

Theo cách đó, nếu bạn thực hiện tìm kiếm trên bàn thì chúng sẽ tương đối nhanh, và tất cả các phép nối và giao diện bình thường của bạn sẽ không bị ảnh hưởng trong tốc độ của chúng.

Bạn cũng có thể kiểm soát số lượng trường chuỗi được lập chỉ mục. Nói cách khác, bạn có thể nói "chỉ lập chỉ mục 5 ký tự đầu tiên" nếu bạn nghĩ rằng điều đó là đủ. Hoặc nếu dữ liệu của bạn có thể tương đối giống nhau, bạn có thể lập chỉ mục cho toàn bộ trường.


3
Tôi nghĩ rằng đặt bất kỳ trí thông minh nào vào một chìa khóa là yêu cầu rắc rối. Họ sẽ duy nhất? Có phải họ đã bắt đầu tất cả các số tài khoản với chữ viết tắt của tiểu bang khi chỉ bắt đầu cho khách hàng di chuyển. Cập nhật một trường - không có vấn đề gì - tất cả các bảng được liên kết theo số tài khoản - thật là một mớ hỗn độn.
JeffO

1
Một ví dụ về việc sử dụng chuỗi làm PK có thể là một bảng cài đặt. ví dụ: settingsNamePK, isUserEditable, isCustomerEditable, v.v. Sau đó, nếu bạn muốn sửa đổi hành vi cài đặt "CẬP NHẬT cài đặt SET ... WHERE settingsNamePK = 'DailyWorkObllation'" sẽ tốt hơn nhiều so với việc phải sử dụng ID và lưu trữ ở đâu đó ánh xạ của ID. Tất nhiên bạn có thể có một PK số nguyên và có tên cài đặt là một khóa duy nhất khác.
MeatPopsicle

Với khóa chính là số nguyên tăng tự động, không nên chèn cũng không bị ảnh hưởng đến tốc độ của chúng?
Dennis

Đối với các nhà phát triển Rails tò mò, đây là cách chỉ định độ dài chỉ mục . Lưu ý rằng SQLite không hỗ trợ độ dài chỉ mục.
Dennis

1

Từ quan điểm hiệu suất - Có chuỗi (PK) sẽ làm chậm hiệu suất khi so sánh với hiệu suất đạt được bằng cách sử dụng số nguyên (PK), trong đó PK ---> Khóa chính.

Từ quan điểm yêu cầu - Mặc dù đây không phải là một phần của câu hỏi của bạn nhưng tôi muốn đề cập. Khi chúng tôi xử lý dữ liệu lớn trên các bảng khác nhau, chúng tôi thường tìm kiếm bộ khóa có thể được đặt cho một bảng cụ thể. Điều này chủ yếu là do có nhiều bảng và chủ yếu là mỗi bảng hoặc một số bảng sẽ liên quan đến nhau thông qua một số quan hệ (một khái niệm về Khóa ngoài). Do đó, chúng tôi thực sự không thể luôn luôn chọn một số nguyên làm Khóa chính, thay vào đó chúng tôi sẽ kết hợp 3, 4 hoặc 5 thuộc tính làm khóa chính cho các bảng đó. Và các khóa đó có thể được sử dụng làm khóa ngoại khi chúng ta liên kết các bản ghi với một số bảng khác. Điều này làm cho nó hữu ích để liên kết các bản ghi trên các bảng khác nhau khi được yêu cầu.

Do đó, đối với việc sử dụng tối ưu - Chúng tôi luôn tạo kết hợp 1 hoặc 2 số nguyên với 1 hoặc 2 thuộc tính chuỗi, nhưng chỉ một lần nữa nếu được yêu cầu.


0

Có thể có một sự hiểu lầm rất lớn liên quan đến chuỗi trong cơ sở dữ liệu. Hầu như tất cả mọi người đã nghĩ rằng đại diện cơ sở dữ liệu của các số nhỏ gọn hơn so với chuỗi. Họ nghĩ rằng trong các số db được thể hiện như trong bộ nhớ. Nhưng nó không phải là sự thật. Trong hầu hết các trường hợp, biểu diễn số gần với chuỗi A hơn như biểu diễn khác.

Tốc độ sử dụng số hoặc chuỗi phụ thuộc nhiều hơn vào việc lập chỉ mục sau đó loại chính nó.


0

Theo mặc định, ASPNetUserIds là 128 chuỗi char và hiệu suất chỉ ở mức tốt.

Nếu khóa ĐÃ là duy nhất trong bảng thì nó phải là Khóa. Đây là lý do tại sao;

Khóa chuỗi chính = Mối quan hệ DB chính xác, Khóa 1 chuỗi (Chính) và Chỉ mục 1 chuỗi (Chính).

Các tùy chọn khác là một int chính điển hình, nhưng nếu chuỗi HAS phải là duy nhất, bạn sẽ vẫn có thể cần phải thêm một chỉ số vì các truy vấn không ngừng để xác nhận hoặc kiểm tra xem độc đáo của nó.

Vì vậy, sử dụng khóa nhận dạng int = Mối quan hệ DB không chính xác, 1 khóa int (Chính), 1 chỉ mục int (Chính), Có thể là một chuỗi Chỉ mục duy nhất và phải xác thực thủ công cùng một chuỗi không tồn tại (có thể giống như kiểm tra sql ).

Để có được hiệu suất tốt hơn sử dụng một int qua một chuỗi cho khóa chính, khi chuỗi HAS phải là duy nhất, nó sẽ phải là một tình huống rất kỳ quặc. Tôi luôn thích sử dụng các khóa chuỗi. Và như một quy tắc tốt, đừng bình thường hóa cơ sở dữ liệu cho đến khi bạn CẦN .

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.