Sự đánh đổi để tăng id so với khóa fulltext cho thiết kế khóa ngoại là gì?


8

Trong rất nhiều thiết kế cơ sở dữ liệu quan hệ, có các trường được tham chiếu trong các bảng khác.

Ví dụ, hãy xem xét một bảng người dùng với tên người dùng duy nhất và bảng thứ hai lưu trữ dữ liệu địa chỉ.

Một cách bố trí có thể, mà tôi muốn nói là cách tiếp cận phổ biến, bởi vì tôi đã quan sát thấy trong hầu hết các phần mềm, là sử dụng id tăng tự động như thế này:

Table users
===========
userId int primary auto_increment
userName varchar unique

Table adressdata
==========
userId int references users.userId
adress_type varchar // for example country
address_value varchar // for example US
(you probably also want to put a unique key on (userId,adress_type))

Đây là cách tôi đã từng làm nó và tôi đã thấy nó như thế nào trong hầu hết các trường hợp.

Một cách khác sẽ là:

Table users
===========
userName varchar primary

Table adressdata
==========
userName varchar references users.userName
adress_type varchar // for example country
address_value varchar // for example US
(you probably also want to put a unique key on (userName,adress_type))

Ở đây chúng tôi lưu trữ tên người dùng đầy đủ cũng trong bảng adressdata.

Đối với tôi điều này có những lợi thế sau:

  • Bạn có thể chọn tên người dùng ngay từ bảng mà không cần phải nối nó với bảng khác. Trong ví dụ này, đây là từ quan điểm ứng dụng có lẽ không liên quan lắm, nhưng nó chỉ là một ví dụ.

  • Có thể dễ dàng hơn để mở rộng cơ sở dữ liệu trong môi trường sao chép chính chủ, vì không có xung đột auto_increment.

Nhưng cũng có nhược điểm:

  • Các yêu cầu không gian cho chỉ mục và dữ liệu (nhưng có liên quan hơn có thể sẽ là chỉ mục) trên trường trong bảng thứ hai cao hơn.
  • Một sự thay đổi của tên người dùng sẽ cần truyền đến tất cả các bảng, điều này tiêu tốn nhiều tài nguyên hơn là chỉ thay đổi nó trong một bảng và để nguyên id như hiện tại.

Theo tôi, làm việc với các trường văn bản sẽ dễ dàng hơn nhiều và không sử dụng id gia tăng và sự đánh đổi là tối thiểu và trong hầu hết các ứng dụng không liên quan.

Tất nhiên, một số đối tượng được xác định bằng số tăng dần theo bản chất của chúng (ví dụ: các bài đăng trên diễn đàn sẽ nhận được id tăng vì có thể không có trường duy nhất nào khác như tiêu đề).

Nhưng trước khi tôi bắt đầu thiết kế bố cục cơ sở dữ liệu của mình theo một cách hoàn toàn khác, tôi muốn biết liệu có những điều tôi không nghĩ tới.

  • Có thực hành tốt nhất?

  • Có những ưu / nhược điểm mà tôi đã không nghĩ và ảnh hưởng của nó có thể phát sinh tại một bài thơ sau này không?

  • Làm thế nào để cá nhân bạn thiết kế cơ sở dữ liệu về các điểm trên và tại sao?

Câu trả lời:


3

Tôi khuyên bạn nên sử dụng id chứ không phải tên người dùng, vì nếu bạn bắt đầu sử dụng tên người dùng làm cột tham gia trong nhiều bảng, bạn phải nhớ cập nhật tất cả chúng.

Khóa ngoại cho usersbảng, trở thành khóa chính của addressdatabảng và khóa chính phải ổn định. Đó là một thực hành tốt để không thay đổi các trường chính. Khóa chính phải tồn tại khi bản ghi được tạo và phải không thay đổi trong toàn bộ thời gian của bản ghi.

Nếu bạn muốn hiểu sâu hơn Cuộc tranh luận về khóa chính tuyệt vời là một bài viết tuyệt vời.


2

Tôi mạnh mẽ trong trại "không sử dụng chìa khóa tự nhiên". Đó là bởi vì tôi đã thấy nó khó như thế nào trên sytem khi chúng được cập nhật và hầu như tất cả các khóa tự nhiên liên quan đến tên của bất kỳ ai đều được cập nhật.

Cơ sở dữ liệu được tối ưu hóa để sử dụng tham gia. Có, bạn có thể lưu một số phép nối bằng cách sử dụng các khóa tự nhiên nhưng hiệu suất đạt được khi bạn cần cập nhật 1.000.000 bản ghi vì một nhóm các khóa tự nhiên đã thay đổi (hoặc thậm chí tùy thuộc vào những gì đang xảy ra) có thể là một logjam lớn.

Tôi sẽ chỉ sử dụng các khóa tự nhiên trong hai điều kiện:

  1. nếu chìa khóa được đảm bảo khá chắc chắn không thay đổi (nghĩ số VIN ô tô)
  2. nếu nó sẽ không bao giờ được sử dụng lại (ngay cả những thứ duy nhất như số điện thoại và email không phải là ứng cử viên cho PK vì chúng được sử dụng lại khi ai đó ngừng sử dụng chúng).

Và tất nhiên, tất cả quá nhiều khóa tự nhiên được cho là duy nhất đều không có. Nếu bạn lo lắng về việc nhân rộng, bạn có thể sử dụng GUID.


1

Bài viết Wikipedia về khóa Surrogate có một vài bit thú vị nằm rải rác xung quanh:

  • "Các thuộc tính xác định duy nhất một thực thể có thể thay đổi, điều này có thể làm mất hiệu lực tính phù hợp của các khóa ghép tự nhiên. " Ví dụ, các hạn chế sau này đối với tên người dùng có thể làm mất hiệu lực các khóa hiện có khi sử dụng khóa tự nhiên user nametrong khi điều này sẽ không ảnh hưởng đến khóa tổng hợp.
  • " Khóa thay thế không thay đổi trong khi hàng tồn tại. " Vì vậy, bạn không cần (thủ công hoặc tự động) thay đổi khóa tầng cho các bảng tham chiếu.
  • " Các giá trị của khóa thay thế được tạo không có mối quan hệ với ý nghĩa trong thế giới thực của dữ liệu được giữ liên tiếp. " Điều này có thể gây khó khăn cho việc kiểm toán.

Tôi tin rằng người đọc chu đáo có thể tìm thấy các điểm bổ sung để xem xét.


Câu trả lời tốt. Nhiều phím tự nhiên có xu hướng thay đổi. Điều này làm cho chúng không phù hợp với các khóa có thể được gọi là khóa ngoại. Có nhiều lý do phù hợp để thay đổi userid của người dùng.
BillThor

1

Tôi sẽ đăng bài từ kinh nghiệm của mình, điều có thể sẽ khác rất nhiều so với những gì các DBA khác nhau có thể đề xuất. Tôi chủ yếu hướng tới sự pha trộn giữa hiệu suất và khả năng bảo trì khi thiết kế cơ sở dữ liệu cho các dự án khác nhau.

Tôi sẽ không bao giờ sử dụng khóa tự nhiên cho khóa chính. Đặc biệt là nếu tôi sử dụng MySQL / InnoDB. Tôi vẫn chưa thấy bất kỳ lợi ích nào trong việc sử dụng khóa tự nhiên, thông thường những gì tôi thấy là hàm ý hiệu suất nếu không có gì. Tôi nhấn mạnh "không bao giờ, bao giờ" chỉ vì các khóa tự nhiên được sử dụng để tạo hiệu suất cho các dự án của tôi. Surrogate (số nguyên) luôn là lựa chọn tốt hơn. Một số có thể không đồng ý, nhưng chúng ta sống trong một thế giới nơi hiệu suất đóng một phần so với lý thuyết.

Khi nói đến THAM GIA, tôi không cố gắng tránh chúng bằng mọi giá nhưng tôi có xu hướng tối ưu hóa chúng. Tôi cố gắng lạm dụng chỉ mục được nhóm của InnoDB (khóa chính) càng nhiều càng tốt. Nếu THAM GIA được thực hiện thông qua PK, thì chúng cực kỳ nhanh. Tôi cũng có xu hướng tránh các FK nơi họ không có ý nghĩa. Thành thật mà nói, tôi sẽ không quan tâm lắm đến tính toàn vẹn dữ liệu khi liên kết người dùng và thông tin địa chỉ của họ. Tôi sẽ thực thi nó khi liên kết hóa đơn với các mặt hàng cho người dùng. Việc lạm dụng FK là một sự quá mức và là cơn ác mộng cần duy trì sau khi bạn tham khảo mọi thứ, nghĩ rằng đó là thiết kế tuyệt vời để gắn kết các mối quan hệ ở mọi nơi. Tại một số thời điểm, mọi thứ cần thay đổi và khi MySQL bắt đầu phàn nàn với lỗi 150 liên tục, bạn chỉ muốn về nhà.

Bạn cũng đã đề cập đến sao chép và tránh xung đột do bản chất của auto_increments. Tôi đã có một dự án nơi chúng tôi có một lượng cơ sở dữ liệu lưu trữ thông tin bán sản phẩm, số lượng cơ sở dữ liệu là khác nhau. Mỗi ngày, cơ sở dữ liệu được sao chép thành một cơ sở dữ liệu "chính" mà chúng tôi đã sử dụng để chạy báo cáo. Cách tôi tránh các xung đột PK là tạo một khóa chính ghép từ phần auto_increment và một phần INT khác biểu thị vị trí nơi bản ghi xuất phát. Bằng cách đó tôi có thể theo dõi mọi thứ đến từ đâu và tôi không mất gì cả (các sản phẩm có cùng ID, chỉ có định danh vị trí được thay đổi).

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.