우정 데이터베이스 구조 설계 : 다중 값 열을 사용해야합니까?


9

User_FriendList다음과 같은 특성을 가진 이라는 테이블이 있다고 가정 해보십시오 .

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

그리고 상기 테이블이 다음 데이터를 가지고 있다고 가정하자 :

 + ---- + --------- + --------------------------- +
 | 아이디 | User_ID | Friendlist_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 |
 + ---- + --------- + --------------------------- +

참고 : 은 ":"때 (콜론) 구분 기호입니다 폭발 로 PHP에서 array.

질문

그래서:

  • 이 "가게"를 할 수있는 편리한 방법이다 IDs(A)의 FriendList?

  • 또는 대신 FriendId각각 하나의 단일 값을 가진 개별 행을 가져야 하며 주어진 목록 의 모든 행을 검색해야 할 때 단순히 다음과 같은 쿼리를 수행해야 SELECT * FROM UserFriendList WHERE UserId = 1합니까?


3
나는 이것을 읽는 것이 좋습니다 : stackoverflow.com/questions/3653462/…
tombom

ID를 사용하지 않고 데이터 품질에 신경 쓰지 않는 한 ID를 저장하는 것이 편리한 방법입니다.
mustaccio

codedodle.com/2014/12/social-network-friends-database.html 이 최고의 솔루션 중 하나 일 수 있다고 생각 합니다.
굽타

답변:


19

개별 정보 관리

비즈니스 도메인에서

  • 사용자가 제로 일 또는 일대 다 가질 수 친구 ;
  • 친구가 처음으로 등록해야합니다 사용자 ; 과
  • 친구 목록 의 단일 값을 검색 및 / 또는 추가 및 / 또는 제거 및 / 또는 수정합니다 .

다음 모여 특정 데이텀 Friendlist_IDs다중 열이 나타내는 정보를 별도의 부재 는 매우 정확한 의미를 전달한다. 따라서, 상기 칼럼

  • 적절한 명시 적 제약 그룹을 수반하고
  • 이 값은 여러 관계 연산 (또는 그 조합)을 통해 개별적으로 조작 될 수 있습니다.

짧은 답변

따라서, 사용자는 각 유지해야 Friendlist_IDs나타내고, (b)의 테이블에 행마다 오로지 하나의 유일한 값을 받아 (a) 컬럼의 값 개념적 레벨 사이에서 일어날 수있다 연결 유형 사용자 즉하는 우정 -as을 다음 섹션에서 예를 들어 보겠습니다.

이런 식으로, (i) 상기 테이블을 수학 관계로 취급 하고 (ii) 컬럼을 수학 관계 속성 으로 취급 할 수 있습니다 ( 물론 MySQL 및 SQL 언어가 허용하는 한도).

왜?

때문에 관계형 데이터 모델 에 의해 만들어진, 박사 E. F. 커드는 , 요구 개최 컬럼으로 구성되어 테이블을 가진 단 하나의 해당 값 도메인 또는 유형 행 당을; 따라서 해당 도메인 또는 해당 유형의 값을 두 개 이상 포함 할 수있는 열이있는 테이블을 선언하면 (1) 수학 관계를 나타내지 않으며 (2) 위에서 언급 한 이론적 프레임 워크에서 제안 된 이점을 얻을 수 없습니다.

사용자 간의 우정 모델링 : 비즈니스 환경 규칙을 먼저 정의

다른 요소들 중에서도 관심있는 개별 측면 사이에 존재하는 상호 관계 유형을 설명해야하는 관련 비즈니스 규칙 의 정의를 통해 해당 개념 스키마를 다른 것보다 먼저 구분하여 데이터베이스를 구성하는 것이 좋습니다. 적용 가능한 개체 유형속성 ; 예 :

  • 사용자는 주로 자신에 의해 식별되는 사용자 아이디
  • 사용자는 교대로 자신의 조합에 의해 식별됩니다 FIRSTNAME , , 성별생년월일
  • 사용자가 번갈아 자신에 의해 식별 아이디
  • 사용자 는 IS 신청인 제로 일 또는 일대의 우정
  • 사용자 는 IS 받는 사람 제로 일 또는 일대의 우정
  • 우정은 주로 자사의 조합에 의해 식별됩니다 RequesterId 하고 AddresseeId

설명 IDEF1X 다이어그램

이러한 방식으로, 나는 이전에 공식화 된 대부분의 규칙을 통합 한 그림 1에 표시된 IDEF1X 1 다이어그램 을 도출 할 수있었습니다 .

그림 1. 사용자 우정 IDEF1X 다이어그램

그림 과 같이 요청자주소 는 지정된 우정에 참여 하는 특정 사용자 가 수행 한 역할 을 나타내는 표기법입니다 .

즉, 우정 엔티티 유형은 동일한 엔티티 유형 (예 : User)다른 발생을 포함 할 수있는 다 대다 (M : N) 카디널리티 비율 의 연관 유형을 나타냅니다 . 따라서 "Bill of Materials"또는 "Parts Explosion"으로 알려진 고전적인 구성의 예입니다.


1 정보 모델링을위한 통합 정의 ( IDEF1X )는1993 년 12 월 미국 국립 표준 기술 연구소 (NIST)에서 표준 으로 확립 한 권장 기법입니다. (a)관계형 모델의 유일한 창시자 , 즉 Dr. EF Codd가 저술 한 초기 이론적 자료; (b) PP Chen 박사가 개발 한 데이터의 개체-관계 관점; 또한 (c) Robert G. Brown이 만든 논리적 데이터베이스 디자인 기법.


예시적인 SQL-DDL 논리 설계

그런 다음 위에 제시된 IDEF1X 다이어그램에서 다음과 같은 DDL 배열을 선언하는 것이 훨씬 "자연적"입니다.

-- 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)
);

이 방식으로 :

  • 기본 테이블 은 개별 엔티티 유형을 나타냅니다.
  • 해당 엔티티 유형 의 유일한 특성을 나타냅니다 .
  • INT, DATETIME, CHAR 등 포함 된 모든 이 특정의 잘 정의 된 세트에 속 하는지 확인하기 위해 특정 데이터 유형 a 가 각 열에 대해 고정됩니다 . 과
  • 모든 테이블에 보유 된 형식의 어설 션 이 개념 스키마에서 결정된 비즈니스 규칙을 충족 하도록하기 위해 다중 제한 조건 b 가 (선언적으로) 구성 됩니다.

단일 값 열의 장점

입증 된 바와 같이, 예를 들면 다음과 같습니다.

  • 열을 참조Friendship.AddresseeId 하는 FOREIGN KEY (간결한 FK)로 제한하면 UserProfile.UserId모든 값이 기존 행을 가리키는 것을 보장 하므로 열에 대해 데이터베이스 관리 시스템 (간결한 DBMS)이 적용하는 참조 무결성을 활용하십시오 .

  • 크리에이트 복합 컬럼의 조합으로 구성 PRIMARY KEY (PK)을 (Friendship.RequesterId, Friendship.AddresseeId)우아하게 모든 삽입 된 행을 구별하고, 자연스럽게, 자신의 보호에 도움, 고유성을 .

    물론 이는 시스템 할당 대리 값 (예 : Microsoft SQL Server 의 IDENTITY 속성 또는 MySQL 의 AUTO_INCREMENT 속성으로 설정된 값) 에 대한 추가 열을 첨부 하고 보조 INDEX가 완전히 불필요한 것을 의미 합니다.

  • DBMS가 적절한 자동 검증 을 처리 할 수 ​​있도록 보유 된 값을 Friendship.AddresseeId정확한 데이터 유형 c (예 : UserProfile.UserIdINT에 대해 설정된 것과 일치해야 함)로 제한하십시오 .

    이 요소는 (a) 해당 내장 유형 기능을 활용하고 (b) 디스크 공간 사용을 최적화하는 데 도움이 될 수 있습니다.

  • 열에 대해 작고 빠른 하위 INDEX를 구성하여 물리적 레벨에서 데이터 검색 을 최적화하십시오. 이러한 물리적 요소는 해당 열과 관련된 쿼리 속도를 크게 높일 수 있습니다 .Friendship.AddresseeId

    예를 들어, 단일 열 INDEX를 Friendship.AddresseeId단독으로 또는 다중 열을 포함 Friendship.RequesterId하고 및 Friendship.AddresseeId또는 둘 다 포함 할 수 있습니다.

  • 동일한 열 (모두 복제, 잘못 입력 등) 내에서 함께 수집 된 고유 한 값을 "검색"함으로써 발생 하는 불필요한 복잡성을 피하십시오 . 상기 과제를 달성하기 위해 자원 및 시간 소모적 인 비 관계형 방법에 의존해야한다.

따라서 각 테이블 열의 유형 d 를 정확하게 표시하기 위해 관련 비즈니스 환경을 신중하게 분석해야하는 여러 가지 이유가 있습니다.

설명했듯이 데이터베이스 디자이너가 수행하는 역할은 (1) 관계형 모델에서 제공 하는 논리적 수준의 이점과 (2) 선택한 DBMS에서 제공 하는 물리적 메커니즘 을 최대한 활용하는 데 가장 중요합니다 .


a , b , c , d DOMAIN 생성 (독특한 관계형 기능)을 지원하는 SQL 플랫폼 (예 : Firebird PostgreSQL )으로작업 할 때각각 해당하는 값 (적절하게 제한되고 때때로 적용되는 값) 만 허용하는 열을 선언 할 수 있습니다. 공유) DOMAIN.


고려중인 데이터베이스를 공유하는 하나 이상의 응용 프로그램

arrays데이터베이스에 액세스하는 응용 프로그램 코드에서 코드 를 사용해야하는 경우 관련 데이터 세트 를 완전히 검색 한 다음 관련 코드 구조에 "바인딩"하거나 발생해야하는 관련 앱 프로세스

단일 값 열의 추가 이점 : 데이터베이스 구조 확장이 훨씬 더 쉽습니다.

AddresseeId예약되고 올바르게 유형이 지정된 열에 데이터 요소를 보관할 경우 얻을 수있는 또 다른 이점은 아래에 설명 할 것처럼 데이터베이스 구조 확장을 상당히 용이하게한다는 것입니다.

시나리오 진행 : 우정 상태 개념 통합

우정 은 시간이 지남에 따라 진화 할 수 있기 때문에 그러한 현상을 추적해야 할 수도 있으므로 (i) 개념 스키마를 확장하고 (ii) 논리적 레이아웃에서 몇 개의 테이블을 더 선언해야합니다. 따라서 새로운 통합을 설명하기 위해 다음 비즈니스 규칙을 마련해 보겠습니다.

  • 우정 일대 보유 FriendshipStatuses을
  • FriendshipStatus는 주로 그것의 조합에 의해 식별된다 RequesterIdAddresseeIdSpecifiedDateTime
  • 사용자 지정 제로 일 또는 일대 다 FriendshipStatuses을
  • 상태 를 분류 제로 일 또는 일대 다 FriendshipStatuses을
  • 상태는 주로 그것으로 식별되는 상태 코드
  • 상태가 번갈아의에 의해 식별 이름

확장 IDEF1X 다이어그램

계속해서 이전 IDEF1X 다이어그램을 확장하여 위에서 설명한 새로운 엔티티 유형 및 상호 관계 유형을 포함 할 수 있습니다. 새로운 요소와 관련된 이전 요소를 나타내는 다이어그램이 그림 2에 나와 있습니다 .

그림 2. 우정 상태 IDEF1X 다이어그램

논리 구조 추가

그 후 다음 선언을 사용하여 DDL 레이아웃을 늘릴 수 있습니다.

--
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)      
);

결과적으로, 주어진 우정 상태 가 최신 상태 가 되어야 할 때마다 , 사용자 는 다음을 포함 하는 새로운 행 을 삽입하기 만하면됩니다 .FriendshipStatus

  • 해당 행 에서 가져온 적합 RequesterId하고 AddresseeId가치있는 것Friendship

  • 새롭고 의미있는 StatusCode가치 MyStatus.StatusCode

  • 정확한 INSERTion 순간, 즉 SpecifiedDateTime서버 기능을 사용하여 신뢰할 수있는 방식으로 검색하고 유지할 수 있도록하는 것이 좋습니다. 과

  • 앱에 새로운 기능 을 추가하여 시스템에 새로 입력 한 SpecifierId값을 나타내는 값입니다 .UserIdFriendshipStatus

이 정도로 MyStatus표가 다음과 같은 데이터를 포함 한다고 가정하자. (a) 최종 사용자, 앱 프로그래머 및 DBA ​​친화적이고 (b) 물리적 구현 레벨 에서 바이트 단위로 작고 빠른 PK 값 — :

 + -——————————- + -————————— +
 | StatusCode | 이름       |
 + -——————————- + -————————— +
 | R | 요청 |
 + ------------ + ----------- +
 | A | 허용됨 |
 + ------------ + ----------- +
 | D | 거부 됨 |
 + ------------ + ----------- +
 | B | 블로 케 |
 + ------------ + ----------- +

따라서 FriendshipStatus테이블은 아래와 같이 데이터를 보유 할 수 있습니다.

 + -———————————- + -———————————————————————————————— ———- + -—————————— ++ —————————— +
 | 요청자 ID | AddresseeId | SpecifiedDateTime        | StatusCode | SpecifierId |
 + -———————————- + -———————————————————————————————— ———- + -—————————— ++ —————————— +
 | 1750 | 1748 | 2016-04-01 16 : 58 : 12.000 | R | 1750 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 | 1750 | 1748 | 2016-04-02 09 : 12 : 05.000 | A | 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 | A | 1750 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +

보시다시피, FriendshipStatus테이블은 시계열 을 구성하는 목적으로 사용 된다고 말할 수 있습니다 .


관련 게시물

다음에 관심이있을 수도 있습니다.

  • 이 답변 에서는 두 가지 유형이 다른 엔터티 유형 간의 공통 다 대다 관계를 처리하는 기본 방법을 제안합니다.
  • 이 다른 답변 을 보여주는 그림 1의 IDEF1X 다이어그램 . MarriageProgeny 라는 엔티티 유형에 특히주의를 기울이십시오 . 이는 "부품 폭발 문제"를 처리하는 방법에 대한 두 가지 예입니다.
  • 이 게시물 에서는 단일 열 내에 다른 정보 조각을 보유하는 방법에 대해 간략하게 설명합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.