Thiết kế cấu trúc cơ sở dữ liệu kết bạn: Tôi có nên sử dụng cột đa trị?


9

Nói rằng tôi có một bảng được gọi User_FriendList, có các đặc điểm sau:

CREATE TABLE User_FriendList (
    ID ...,
    User_ID...,
    FriendList_IDs...,
    CONSTRAINT User_Friendlist_PK PRIMARY KEY (ID)
);

Và chúng ta hãy giả sử rằng bảng đã nói chứa dữ liệu sau:

 + ---- + --------- + --------------------------- +
 | ID | Người dùng_ID | Danh sách bạn bè_IDs             |
 + ---- + --------- + --------------------------- +
 | 1 | 102 | 2: 15: 66: 35: 26: 17: |
 + ---- + --------- + --------------------------- +
 | 2 | 114 | 1: 12: 63: 33: 24: 16: 102 |
 + ---- + --------- + --------------------------- +
 | 3 | 117 | 6: 24: 52: 61: 23: 90: 97: 118 |
 + ---- + --------- + --------------------------- +

Lưu ý: Số: Khác (dấu hai chấm) là dấu phân cách khi phát nổ trong PHP thành một array.

Câu hỏi

Vì thế:

  • Đây có phải là một cách thuận tiện để lưu trữ trên cửa hàng IDscủa mình FriendListkhông?

  • Hoặc, thay vào đó, tôi nên có các hàng riêng lẻ chỉ có một FriendIdgiá trị duy nhất trong mỗi giá trị đó và khi tôi cần truy xuất tất cả các hàng của danh sách đã cho , chỉ cần thực hiện một truy vấn như thế SELECT * FROM UserFriendList WHERE UserId = 1nào?


3
Tôi khuyên bạn nên đọc cái này: stackoverflow.com/questions/3653462/ từ
Tombom

Đây là một cách thuận tiện để lưu trữ ID, miễn là bạn không có kế hoạch làm bất cứ điều gì với chúng và không đặc biệt quan tâm đến chất lượng dữ liệu.
mustaccio

Tôi nghĩ rằng codedodle.com/2014/12/social-network-friends-database.html có thể là một trong những giải pháp tốt nhất.
Gupta

Câu trả lời:


19

Quản lý một mẩu thông tin cá nhân

Giả sử rằng, trong lĩnh vực kinh doanh của bạn,

  • một tài khoản có thể có zero-một-hoặc-nhiều bạn bè ;
  • một người bạn đầu tiên phải được đăng ký dưới dạng một tài khoản ; và
  • bạn sẽ tìm kiếm và / hoặc thêm và / hoặc xóa và / hoặc sửa đổi các giá trị đơn lẻ của Danh sách bạn bè ;

sau đó mỗi mốc dữ liệu cụ thể được thu thập trong Friendlist_IDscột đa trị đại diện cho một phần thông tin riêng biệt mang một ý nghĩa rất chính xác. Do đó, cột nói

  • đòi hỏi một nhóm thích hợp của các ràng buộc rõ ràng và
  • các giá trị của nó có khả năng bị thao túng riêng lẻ bằng một số hoạt động quan hệ (hoặc kết hợp chúng).

Câu trả lời ngắn

Do đó, bạn nên giữ lại mỗi Friendlist_IDsgiá trị trong (a) một cột chấp nhận độc quyền một giá trị duy nhất cho mỗi hàng trong (b) một bảng đại diện cho khái niệm cấp loại hiệp hội có thể diễn ra giữa người sử dụng , ví dụ, một Hữu -Như Tôi sẽ làm gương trong các phần sau đây.

Theo cách này, bạn sẽ có thể xử lý (i) bảng đã nói như một mối quan hệ toán học và (ii) cột đã nói là một thuộc tính quan hệ toán học giống như MySQL và cho phép phương ngữ SQL của nó, tất nhiên là.

Tại sao?

Bởi vì mô hình dữ liệu quan hệ , được tạo bởi Tiến sĩ E. F. Codd , yêu cầu có các bảng bao gồm các cột chứa chính xác một giá trị của miền hoặc loại áp dụng trên mỗi hàng; do đó, việc khai báo một bảng có một cột có thể chứa nhiều hơn một giá trị của miền hoặc loại trong câu hỏi (1) không thể hiện mối quan hệ toán học và (2) sẽ không cho phép đạt được các lợi thế được đề xuất trong khung lý thuyết đã nói ở trên.

Mô hình hóa mối quan hệ bạn bè giữa những người dùng : Trước tiên hãy xác định các quy tắc môi trường kinh doanh

Tôi đặc biệt khuyên bạn nên bắt đầu định hình một cơ sở dữ liệu phân định trước khi có bất cứ điều gì khác, đó là lược đồ khái niệm tương ứng theo định nghĩa của các quy tắc kinh doanh có liên quan , trong số các yếu tố khác, phải mô tả các loại mối quan hệ tồn tại giữa các khía cạnh khác nhau của lợi ích, nghĩa là , các loại thực thể áp dụng và các thuộc tính của chúng ; ví dụ:

  • Một tài chủ yếu được xác định bởi mình UserId
  • Một tài khoản được luân phiên xác định bởi sự kết hợp của mình FirstName , LastName , Giới tính , và Ngày sinh
  • Một tài khoản được luân phiên xác định bởi mình Tên đăng nhập
  • Một tài khoảnYêu Cầu của zero-một-hoặc-nhiều Tình bạn
  • Một tài khoảnNgười nhận của zero-một-hoặc-nhiều Tình bạn
  • Một tình bạn chủ yếu được xác định bằng sự kết hợp giữa RequesterIdAddresseeId của nó

Sơ đồ IDEF1X tiếp xúc

Theo cách này, tôi đã có thể rút ra sơ đồ IDEF1X 1 được hiển thị trong Hình 1 , tích hợp hầu hết các quy tắc được xây dựng trước đó:

Hình 1. Sơ đồ bạn bè IDEF1X

Như mô tả, Yêu CầuNgười nhận là denotations mà diễn tả vai trò thực hiện bởi các cụ Users rằng tham gia vào một trao Hữu nghị .

Như vậy, loại thực thể Hữu nghị mô tả một loại kết hợp tỷ lệ số lượng nhiều-nhiều (M: N) có thể liên quan đến các khoảng thời gian khác nhau của cùng một loại thực thể, tức là Người dùng . Như vậy, đây là một ví dụ về cấu trúc cổ điển được biết đến với tên gọi Bill Bill của Vật liệu.


1 Định nghĩa tích hợp cho mô hình hóa thông tin ( IDEF1X ) là một kỹ thuật rất được khuyến khích, được thành lập như một tiêu chuẩn vào tháng 12 năm 1993 bởi Viện Tiêu chuẩn và Công nghệ Quốc gia Hoa Kỳ(NIST). Nó hoàn toàn dựa trên (a) các tài liệu lý thuyết ban đầu được tác giả bởi người khởi tạo duy nhất của mô hình quan hệ, tức là, Tiến sĩ EF Codd ; trên (b)chế độ xem mối quan hệ thực thể của dữ liệu, được phát triển bởi Tiến sĩ PP Chen ; và cũng trên (c) Kỹ thuật thiết kế cơ sở dữ liệu logic, được tạo bởi Robert G. Brown.


Thiết kế logic SQL-DDL minh họa

Sau đó, từ sơ đồ IDEF1X được trình bày ở trên, việc khai báo một sắp xếp DDL giống như sắp xếp theo sau là nhiều hơn nữa.

-- You should determine which are the most fitting 
-- data types and sizes for all the table columns 
-- depending on your business context characteristics.

-- At the physical level, you should make accurate tests 
-- to define the mostconvenient INDEX strategies based on 
-- the pertinent query tendencies.

-- As one would expect, you are free to make use of 
-- your preferred (or required) naming conventions. 

CREATE TABLE UserProfile ( -- Represents an independent entity type.
    UserId          INT      NOT NULL,
    FirstName       CHAR(30) NOT NULL,
    LastName        CHAR(30) NOT NULL,
    BirthDate       DATE     NOT NULL,
    GenderCode      CHAR(3)  NOT NULL,
    Username        CHAR(20) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT UserProfile_PK  PRIMARY KEY (UserId),
    CONSTRAINT UserProfile_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
        FirstName,
        LastName,
        GenderCode,
        BirthDate
    ),
    CONSTRAINT UserProfile_AK2 UNIQUE (Username) -- Single-column ALTERNATE KEY.
);

CREATE TABLE Friendship ( -- Stands for an associative entity type.
    RequesterId     INT      NOT NULL,
    AddresseeId     INT      NOT NULL, -- Fixed with a well-delimited data type.
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Friendship_PK            PRIMARY KEY (RequesterId, AddresseeId), -- Composite PRIMARY KEY.
    CONSTRAINT FriendshipToRequester_FK FOREIGN KEY (RequesterId)
        REFERENCES UserProfile (UserId),
    CONSTRAINT FriendshipToAddressee_FK FOREIGN KEY (AddresseeId)
        REFERENCES UserProfile (UserId)
);

Theo cách này:

  • mỗi bảng cơ sở đại diện cho một loại thực thể riêng lẻ;
  • mỗi cột là viết tắt của một thuộc tính duy nhất của loại thực thể tương ứng ;
  • một cụ dữ liệu gõ một là cố định cho mỗi cột để đảm bảo rằng tất cả các giá trị nó chứa thuộc về một cụ thể và được xác định rõ bộ , có thể là INT, DATETIME, CHAR, vv .; và
  • nhiều ràng buộc b được cấu hình (khai báo) để đảm bảo rằng các xác nhận ở dạng hàng được giữ lại trong tất cả các bảng đáp ứng các quy tắc nghiệp vụ được xác định tại lược đồ khái niệm.

Ưu điểm của cột có giá trị đơn

Như đã chứng minh, bạn có thể, vd:

  • Tận dụng tính toàn vẹn tham chiếu được thi hành bởi hệ thống quản lý cơ sở dữ liệu (DBMS for brevity) cho Friendship.AddresseeIdcột, vì việc ràng buộc nó như là một FOREIGN KEY (FK cho phép ngắn gọn) làm cho tham chiếu đến UserProfile.UserIdcột đảm bảo rằng mọi giá trị đều trỏ đến một hàng hiện có .

  • Tạo một hỗn PRIMARY KEY (PK) tạo thành từ sự kết hợp của các cột (Friendship.RequesterId, Friendship.AddresseeId), giúp thanh lịch phân biệt tất cả các hàng chèn vào và, một cách tự nhiên, bảo vệ của họ độc đáo .

    Tất nhiên, điều này có nghĩa là phần đính kèm của một cột bổ sung cho các giá trị thay thế được gán bởi hệ thống (ví dụ: một tệp được thiết lập với thuộc tính IDENTITY trong Microsoft SQL Server hoặc với thuộc tính AUTO_INCREMENT trong MySQL) và INDEX hỗ trợ là hoàn toàn thừa .

  • Hạn chế các giá trị được giữ lại trong Friendship.AddresseeIdmột loại dữ liệu chính xác c (phải khớp với, ví dụ, giá trị được thiết lập cho UserProfile.UserId, trong trường hợp này là INT), để DBMS đảm nhiệm việc xác thực tự động thích hợp.

    Yếu tố này cũng có thể giúp (a) sử dụng các hàm loại tích hợp tương ứng và (b) tối ưu hóa việc sử dụng không gian đĩa .

  • Tối ưu hóa truy xuất dữ liệu ở cấp độ vật lý bằng cách định cấu hình INDEX cấp dưới nhỏ và nhanh cho Friendship.AddresseeIdcột, vì các yếu tố vật lý này có thể hỗ trợ đáng kể trong việc tăng tốc các truy vấn liên quan đến cột đã nói.

    Chắc chắn, bạn có thể, ví dụ, đưa ra một INDEX Friendship.AddresseeIdmột cột cho một mình, một cột nhiều cột bao gồm Friendship.RequesterIdFriendship.AddresseeIdhoặc cả hai.

  • Tránh sự phức tạp không cần thiết được giới thiệu bởi việc tìm kiếm các giá trị khác biệt được đưa vào cùng nhau trong cùng một cột (rất có thể bị trùng lặp, gõ sai, v.v.), một hành động cuối cùng sẽ làm chậm chức năng của hệ thống của bạn, bởi vì bạn sẽ phải sử dụng các phương pháp không liên quan đến tài nguyên và tốn thời gian để hoàn thành nhiệm vụ nói trên.

Vì vậy, có nhiều lý do yêu cầu phân tích môi trường kinh doanh có liên quan một cách cẩn thận để đánh dấu loại d của từng cột trong bảng một cách chính xác.

Như đã giải thích, vai trò của nhà thiết kế cơ sở dữ liệu là tối quan trọng để sử dụng tốt nhất (1) các lợi ích mức logic được cung cấp bởi mô hình quan hệ và (2) các cơ chế vật lý được cung cấp bởi DBMS.


a , b , c , d Rõ ràng, khi làm việc với các nền tảng SQL (ví dụ: Firebird PostgreQuery ) hỗ trợ tạo DOMAIN (mộttính năng quan hệ đặc biệt), bạn có thể khai báo các cột chỉ chấp nhận các giá trị thuộc về chúng (bị ràng buộc phù hợp và đôi khi chia sẻ) TÊN MIỀN.


Một hoặc nhiều chương trình ứng dụng chia sẻ cơ sở dữ liệu đang được xem xét

Khi bạn phải sử dụng arraysmã của chương trình ứng dụng để tích hợp cơ sở dữ liệu, bạn chỉ cần truy xuất đầy đủ (các) bộ dữ liệu có liên quan và sau đó, gắn kết nó với cấu trúc mã liên quan hoặc thực thi cấu trúc mã liên quan hoặc thực thi quá trình (các) ứng dụng liên quan sẽ diễn ra.

Lợi ích khác của các cột có giá trị đơn: Phần mở rộng cấu trúc cơ sở dữ liệu dễ dàng hơn nhiều

Một lợi thế khác của việc giữ AddresseeIdđiểm dữ liệu trong cột được bảo lưu và đánh máy đúng là nó tạo điều kiện thuận lợi cho việc mở rộng cấu trúc cơ sở dữ liệu, như tôi sẽ minh họa bên dưới.

Diễn biến kịch bản: Kết hợp khái niệm Tình trạng hữu nghị

Tình bạn có thể phát triển theo thời gian, bạn có thể phải theo dõi hiện tượng như vậy, do đó bạn sẽ phải (i) mở rộng lược đồ khái niệm và (ii) khai báo thêm một vài bảng trong bố cục logic. Vì vậy, hãy để chúng tôi sắp xếp các quy tắc kinh doanh tiếp theo để phân định các kết hợp mới:

  • Một tình bạn giữ một đến nhiều FriendshipStatuses
  • Một FriendshipStatus chủ yếu được xác định bởi sự kết hợp của nó RequesterId , nó AddresseeId và nó SpecifiedDateTime
  • Một tài khoản quy định cụ thể số không-một-hoặc-nhiều FriendshipStatuses
  • Một Status phân loại zero-one-hoặc-nhiều FriendshipStatuses
  • Một Tình trạng này chủ yếu được xác định bởi nó StatusCode
  • Một trạng thái được xác định xen kẽ bởi Tên của nó

Sơ đồ IDEF1X mở rộng

Kế tiếp, sơ đồ IDEF1X trước đó có thể được mở rộng để bao gồm các loại thực thể mới và các loại tương quan được mô tả ở trên. Một sơ đồ mô tả các yếu tố trước đó được liên kết với các yếu tố mới được trình bày trong Hình 2 :

Hình 2. Sơ đồ trạng thái tình bạn IDEF1X

Bổ sung cấu trúc logic

Sau đó, chúng ta có thể kéo dài bố cục DDL bằng các khai báo sau:

--
CREATE TABLE MyStatus ( -- Denotes an independent entity type.
    StatusCode CHAR(1)  NOT NULL,
    Name       CHAR(30) NOT NULL,
    --
    CONSTRAINT MyStatus_PK PRIMARY KEY (StatusCode),
    CONSTRAINT MyStatus_AK UNIQUE      (Name) -- ALTERNATE KEY.
); 

CREATE TABLE FriendshipStatus ( -- Represents an associative entity type.
    RequesterId       INT      NOT NULL,
    AddresseeId       INT      NOT NULL,
    SpecifiedDateTime DATETIME NOT NULL,
    StatusCode        CHAR(1)  NOT NULL,
    SpecifierId       INT      NOT NULL,
    --
    CONSTRAINT FriendshipStatus_PK             PRIMARY KEY (RequesterId, AddresseeId, SpecifiedDateTime), -- Composite PRIMARY KEY.
    CONSTRAINT FriendshipStatusToFriendship_FK FOREIGN KEY (RequesterId, AddresseeId)
        REFERENCES Friendship  (RequesterId, AddresseeId), -- Composite FOREIGN KEY.
    CONSTRAINT FriendshipStatusToMyStatus_FK   FOREIGN KEY (StatusCode)
        REFERENCES MyStatus    (StatusCode),
    CONSTRAINT FriendshipStatusToSpecifier_FK  FOREIGN KEY (SpecifierId)
        REFERENCES UserProfile (UserId)      
);

Do đó, mỗi khi Tình trạng của một Tình bạn nhất định cần được cập nhật, Người dùng sẽ chỉ phải XÁC NHẬN một FriendshipStatushàng mới , có chứa:

  • phù hợp RequesterIdAddresseeIdgiá trị -taken từ liên quan đến Friendshiprow-;

  • StatusCodegiá trị mới và có ý nghĩa Rút tiền từ MyStatus.StatusCode-;

  • tức thì chính xác, tức là, SpecifiedDateTimesử dụng chức năng máy chủ để bạn có thể truy xuất và giữ lại nó một cách đáng tin cậy và

  • các SpecifierIdgiá trị mà sẽ chỉ ra tương ứng UserIdmà bước vào mới FriendshipStatusvào hệ thống -ideally, với sự trợ giúp của ứng dụng của bạn (s) facilities-.

Ở mức độ đó, chúng ta giả sử rằng MyStatusbảng chứa các dữ liệu sau đây với các giá trị PK có (a) người dùng cuối, lập trình viên ứng dụng và thân thiện với DBA và (b) nhỏ và nhanh về các byte ở mức triển khai vật lý -:

 + -10
 | Mã trạng thái | Tên       |
 + -10
 | R | Yêu cầu |
 + ------------ + ----------- +
 | Một | Được chấp nhận |
 + ------------ + ----------- +
 | D | Từ chối |
 + ------------ + ----------- +
 | B | Bloqued |
 + ------------ + ----------- +

Vì vậy, FriendshipStatusbảng có thể chứa dữ liệu như hiển thị bên dưới:

 + -Hãy trong khi bạn đang ở trong tình yêu Mầm tím- +
 | Người yêu cầu | Địa chỉ | SpecifiedDateTime        | Mã trạng thái | SpecifierId |
 + -Hãy trong khi bạn đang ở trong tình yêu Mầm tím- +
 | 1750 | 1748 | 2016-04-01 16: 58: 12.000 | R | 1750 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 | 1750 | 1748 | 2016-04 / 02 09: 12: 05.000 | Một | 1748 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 | 1750 | 1748 | 2016-04-04 10: 57: 01.000 | B | 1750 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 | 1750 | 1748 | 2016-04-07 07: 33: 08.000 | R | 1748 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 | 1750 | 1748 | 2016-04-08 12: 12: 09.000 | Một | 1750 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +

Như bạn có thể thấy, có thể nói rằng FriendshipStatusbảng phục vụ mục đích bao gồm một chuỗi thời gian .


Bài viết liên quan

Bạn cũng có thể quan tâm:

  • Câu trả lời này trong đó tôi đề xuất một phương pháp cơ bản để giải quyết mối quan hệ nhiều-nhiều-chung giữa hai loại thực thể không giống nhau.
  • Sơ đồ IDEF1X được hiển thị trong Hình 1 minh họa câu trả lời khác này . Đặc biệt chú ý đến các loại thực thể có tên Hôn nhânProgeny , bởi vì họ là hai ví dụ về làm thế nào để xử lý các “Phụ nổ Problem”.
  • Bài đăng này trình bày một sự cân nhắc ngắn gọn về việc nắm giữ các mẩu thông tin khác nhau trong một cột.
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.