Tại sao việc sử dụng các khóa chuỗi thường được coi là một ý tưởng tồi?


23

Điều này đã được lỗi tôi cho một lúc. Hầu hết thời gian, khi nói đến việc lưu trữ dữ liệu trong các cấu trúc như hashtables, lập trình viên, sách và bài viết đều nhấn mạnh rằng các phần tử lập chỉ mục trong các cấu trúc đã nói theo các giá trị String được coi là thông lệ xấu. Tuy nhiên, cho đến nay, tôi đã không tìm thấy một nguồn như vậy để giải thích TẠI SAO nó được coi là thực hành xấu. Có phụ thuộc vào ngôn ngữ lập trình không? Trên khung cơ bản? Về việc thực hiện?

Lấy hai ví dụ đơn giản, nếu nó giúp:

Một bảng giống như SQL trong đó các hàng được lập chỉ mục bởi khóa chính Chuỗi.

Một từ điển .NET trong đó các khóa là Chuỗi.


9
Có khóa chuỗi không phải là một ý tưởng tồi nói chung. Tôi nghi ngờ những tuyên bố đó đã được thực hiện trong bối cảnh có sẵn loại khóa tốt hơn. Tôi có từ điển .net với các phím chuỗi mọi lúc. Bạn có thể cho một số ví dụ về yêu cầu này?
CodeInChaos

3
Bạn thường muốn các khóa chính không thay đổi trong suốt vòng đời của một đối tượng / hàng. Vì vậy, ví dụ usernamenhư khóa chính của usersbảng có thể không phải là ý tưởng tốt nhất và bạn thích id tăng tự động. Nhưng đó usernamelà một chuỗi chỉ là sự cố, là một tài sản có thể thay đổi là vấn đề chính
CodeInChaos

Trong cơ sở dữ liệu, hãy xem xét cách lập chỉ mục chuỗi trái ngược với số nguyên.

@CodesInChaos Tôi ước tôi có thể nhớ nơi tôi đã tìm thấy hầu hết các trường hợp, nhưng bây giờ tôi có thể dán bit khiến tôi nhớ về vấn đề này. Đó là từ một slideshow GDC của Valve đã thảo luận về các cuộc đối thoại trò chơi và lưu trữ các sự kiện về thế giới trong các cặp <key = string, value = object>.

2
Dây là tốt. Không phải là chuỗi 'ma thuật'. Vì vậy, khi sử dụng bảng băm, hãy đảm bảo bạn không có chuỗi trần trong mã của mình. Bạn nên tránh các giá trị văn bản lớn làm khóa vì chúng không hoạt động tốt, nhưng trong hầu hết các tình huống trong thế giới thực, một chuỗi văn bản ngắn cũng nhanh như một số nguyên (chúng không phải là cơ sở dữ liệu lớn). Bạn cũng có thể sử dụng các khóa thay thế, ví dụ, khóa chính là một số nhưng cũng có một chuỗi 'sên' hoặc chuỗi duy nhất cũng là duy nhất.
ipaul

Câu trả lời:


17

Tất cả đều phải làm với hai điều cơ bản:

1) Tốc độ tra cứu (trong đó số nguyên cho giá vé tốt hơn nhiều)

2) Kích thước của các chỉ mục (trong đó các chỉ mục chuỗi sẽ bùng nổ)

Bây giờ tất cả phụ thuộc vào nhu cầu của bạn và kích thước của tập dữ liệu. Nếu một bảng hoặc một bộ sưu tập có 10-20 phần tử trong đó, loại khóa là không liên quan. Nó sẽ rất nhanh ngay cả với một phím chuỗi.

PS Có thể không liên quan đến câu hỏi của bạn, nhưng Hướng dẫn cũng bị coi là xấu đối với các khóa cơ sở dữ liệu (Hướng dẫn 16 byte so với số nguyên 4 byte). Trên khối lượng dữ liệu lớn Hướng dẫn làm chậm tìm kiếm.


Không phải lúc nào - GUID gia tăng là có thể. Các chỉ mục sẽ vẫn lớn hơn, nhưng hình phạt tra cứu sẽ không tệ như vậy.
Sam

6
Thật ra họ vẫn ổn. Bạn phải xem xét mối quan hệ giữa thời gian IO của đĩa thời gian và so sánh các giá trị trong bộ nhớ. Vì thời gian truy cập đĩa vượt quá so sánh bộ nhớ, điều duy nhất thực sự quan trọng trong việc phân tích hiệu suất cơ sở dữ liệu là IO. Cho dù khóa là GUID, chuỗi hoặc số nguyên không thực sự quan trọng. Kích thước chỉ mục ảnh hưởng đến số lượng giá trị chỉ mục phù hợp trong một trang, nhưng liệu khóa có phải là int 4 byte (có thể không đủ lớn và không thể được tạo bởi máy khách) hay giá trị 16 byte không phải là vấn đề đáng quan tâm. Trong một số cơ sở dữ liệu, rowId có thể có kích thước 16 byte.
ipaul

9

Có một vấn đề nữa với việc sử dụng chuỗi làm khóa, hoặc chính xác hơn là sử dụng chuỗi ký tự làm khóa, đặt các lý do hiệu suất / hiệu suất thuần túy sang một bên. Typose. Nếu bạn sử dụng chuỗi ký tự chuỗi làm khóa trong từ điển, bạn sẽ tự đặt ra một bất ngờ khó chịu khi "ReceiverId"trở thành một "RecieverId". Thiết lập các hằng số để lưu trữ các giá trị chính và sử dụng lại chúng bất cứ khi nào bạn truy cập từ điển.

Rõ ràng và rõ ràng, bạn có thể nói, nhưng một số lượng lớn các ví dụ mã .NET trên web sử dụng chuỗi ký tự, truyền bá thực tiễn đáng ngờ này. ASP.NET với tất cả các Phiên, ViewStates và QueryParams rải rác trên cơ sở mã là đặc biệt có tội ở đây.


IMHO không tầm thường. Tôi cũng đã thấy các trường hợp có khóa "1""1 "trong cùng một bảng.
pswg

Thậm chí còn gây cười hơn khi bạn ném độ nhạy trường hợp vào hỗn hợp. Nhìn thấy vô số người bao gồm cả bản thân tôi vấp ngã trực tiếp vào đó.
Tony Hopkinson

Thậm chí tốt hơn so với việc sử dụng các hằng số, trong C # ít nhất, là sử dụng Biểu thức thay thế. Bằng cách đó, bạn có thể tạo các chuỗi của mình từ tên của các phương thức / thuộc tính, v.v ... để tra cứu chuỗi của bạn trở nên an toàn và thân thiện với cấu trúc lại.
DêInTheMachine

4

Có nhiều sự đánh đổi ở đây. Trên thực tế tôi thường xuyên sử dụng các khóa chuỗi, nhưng tôi thường bao gồm các khóa phụ thay thế cho các phép nối (rõ ràng nó sẽ là cách khác nếu tôi đang sử dụng MySQL). Tuy nhiên, có những trường hợp tôi không.

Đầu tiên tôi là một người hâm mộ khai báo các khóa tự nhiên là khóa chính trong đó db có thể xử lý tốt việc này (ví dụ PostgreQuery). Điều này giúp với việc chuẩn hóa và làm cho thiết kế cơ sở dữ liệu rõ ràng hơn. Phím thay thế làm cho việc tham gia dễ dàng hơn.

Có hai lý do tôi thường thêm khóa thay thế:

  1. Không phải lúc nào cũng rõ ràng khóa tự nhiên là gì. Đôi khi những điều này phải được thay đổi. Thay đổi khóa tổng hợp tự nhiên khi được sử dụng để tham gia và tính toàn vẹn tham chiếu rất phức tạp và dễ bị lỗi.

  2. Tham gia hiệu suất trên các phím tổng hợp có vấn đề và một khi bạn đi xuống tuyến đường tự nhiên, bạn sẽ bị kẹt ở đó.

Tuy nhiên, trong trường hợp khóa tự nhiên là xác định, cột đơn và văn bản, tôi thường tham gia vào khóa chuỗi. Lý do của tôi để làm như vậy là điều này thường tránh tham gia vào việc tra cứu. Việc sử dụng phổ biến nhất là cung cấp thiết kế db thích hợp xung quanh trường hợp sử dụng các loại enum. Trong hầu hết các trường hợp, những điều này không yêu cầu tham gia thêm cho các truy vấn thông thường. Vì vậy, đây là trường hợp, các phím chuỗi như các phím tham gia có ý nghĩa hoàn hảo.

Ví dụ: trong LedgerSMB, chúng tôi lưu trữ các phân loại tài khoản. Chúng được xác định bởi tham chiếu chuỗi. Và một số dữ liệu khác được lưu trữ với tham chiếu chuỗi được sử dụng để thực thi các quy tắc liên quan đến kết hợp các phân loại có thể ảnh hưởng đến tài khoản. Thời gian duy nhất mà logic là cần thiết là khi lưu một tập hợp các phân loại, vì vậy chúng tôi tham gia vào khóa chuỗi.

Về lý do tại sao mặc định sẽ là khóa số nguyên, tôi không nghĩ đó chỉ là một câu hỏi về kích thước chỉ mục. Một vấn đề lớn là quản lý chìa khóa. Vì khóa này là tùy ý và bạn có thể xử lý hàng triệu bản ghi, bạn phải có cách tạo các chuỗi duy nhất. Có những trường hợp mọi người sử dụng UUID cho việc này, nhưng có khả năng xảy ra va chạm UUID khác không, và khi hàng tỷ bản ghi được lưu trữ, cơ hội này trở nên đủ cao để người ta có thể thấy trong khi khả năng va chạm với các loại số nguyên tăng là 0 theo định nghĩa.


Nó không phải là không nếu bạn quản lý để làm cho kiểu số nguyên bao quanh trở về số không. Đối với một kiểu unsigned 32-bit, mà chỉ là 4G đi, đó là đáng lo ngại gần gũi với “hàng tỷ hồ sơ” ...
Donal Fellows

Nếu bạn có một db mà bạn có thể báo "lỗi thay vì bao quanh" thì đó là số không. Ở mọi mức độ, việc quản lý khả năng va chạm với số nguyên tăng dần sẽ dễ dàng hơn so với các giá trị giả ngẫu nhiên.
Chris Travers

1

Có một số vấn đề tiềm ẩn khi sử dụng chuỗi làm khóa, đặc biệt là khi nói đến các bảng giống như sql. Như @bunny đã đề cập, các chỉ mục cho các bảng của bạn sẽ lớn hơn, nhưng tôi nghĩ đáng kể hơn, bất kỳ mối quan hệ khóa ngoại nào với bảng sẽ liên quan đến các bảng BÓNG có chứa chuỗi trái ngược với mã định danh (số nguyên) nhẹ hơn . Nếu bạn thấy rằng thậm chí còn có nhiều bảng hơn với các tham chiếu đến đầu tiên, các khóa chuỗi sẽ được phổ biến trong cơ sở dữ liệu của bạn.


1

Bản thân nó không phải là một ý tưởng tồi, nó thường với 20/20 trở ngại cho một sự thỏa hiệp thiết kế kém. Tính linh hoạt và phạm vi của chuỗi so với chi phí và độ phức tạp bổ sung.

Nếu số nguyên thực hiện phạm vi công việc khôn ngoan và phần lớn quá trình xử lý đắt tiền không cần biết số nguyên biểu thị điều gì, hãy sử dụng số nguyên.


0

Bạn bằng cách nào đó đã lấy dữ liệu sai từ Hashtable.

Ý của bạn là "DaytimeTelPhone" hay "EveningTelPhone"?

hoặc là

Ý bạn là 1234567 hay 1234576?

Trong khi các con số được cho là hiệu quả hơn cho máy , bất cứ khi nào mọi thứ trở nên tồi tệ (và chúng làm như vậy), nó sẽ thuộc về bạn và tôi hiểu được điều gì đã xảy ra và tại thời điểm đó, việc tiết kiệm một vài byte lưu trữ và một vài micro (nano?) - giây xử lý mất đi sự rõ ràng mỗi lần.


1
Và do đó, bạn kết thúc với một danh sách các hằng số, sử dụng tên của hằng số trong mã của bạn để biểu thị số ma thuật ... Java đưa ra giải cứu để trừu tượng hóa nó hơn nữa và để lại cho bạn chỉ tên và có thứ tự lập bản đồ vô hình.
jwenting

-1

Rất nhiều sự đánh đổi và không ai trả lời đúng. Nhiều lập trình viên sẽ không bao giờ xem xét việc sử dụng các khóa chuỗi trong cơ sở dữ liệu vì họ không biết về băm và cách thức hoạt động của cơ sở dữ liệu. Các khóa chuỗi miễn là chúng cực kỳ ổn định hoặc vô nghĩa (thay thế), là một lựa chọn thiết kế tốt trong nhiều trường hợp.


2
Câu trả lời này không thêm bất cứ điều gì chưa được nói trong các câu trả lời khác, mà nói nó tốt hơn.
Martijn Pieters

-2

khóa chuỗi sẽ có ý nghĩa, khi nói đến bảng tra cứu với khoảng 10 - 100 bản ghi chuỗi ngắn; dữ liệu liên quan dễ đọc hơn + ví dụ theo dõi thay đổi (id số / hướng dẫn so với chuỗi, ví dụ: "Quản trị viên"); btw, cơ sở dữ liệu thành viên ASP.NET sử dụng các khóa chuỗi cho AspNetRoles.

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.