데이터베이스 설계 : "(다 대다) 대 다"관계 정규화


14

짧은 버전

기존 다 대다 조인에서 각 쌍에 고정 된 수의 추가 속성을 추가해야합니다. 기본 다이어그램을 확장하여이를 달성하기위한 가장 좋은 방법은 옵션 1-4 중 아래 다이어그램으로 건너 뛰는 것입니다. 아니면 여기에 고려하지 않은 더 나은 대안이 있습니까?

더 긴 버전

현재 중간 조인 테이블을 통해 다 대 다 관계로 두 개의 테이블이 있습니다. 기존 객체 쌍에 속하는 속성에 대한 추가 링크를 추가해야합니다. 속성 테이블의 한 항목이 여러 쌍에 적용되거나 한 쌍에 여러 번 사용될 수도 있지만 각 쌍에 대해 고정 된 수의 속성이 있습니다. 이 작업을 수행하는 가장 좋은 방법을 결정하려고하는데 상황을 생각하는 방법을 정렬하는 데 문제가 있습니다. 의미 적으로 그것은 다음과 같이 잘 묘사 할 수있는 것처럼 보입니다.

  1. 고정 된 수의 추가 속성의 한 세트에 연결된 한 쌍
  2. 많은 추가 속성에 연결된 한 쌍
  3. 하나의 속성 집합에 연결된 많은 (2) 개체
  4. 많은 속성에 연결된 많은 개체

나는 각각 고유 ID를 가진 X와 Y의 두 가지 객체 유형 objx_objy과 열이 있는 연결 테이블 x_idy_id로 구성되어 있으며 링크의 기본 키를 구성합니다. 각 X는 많은 Y와 관련 될 수 있으며 그 반대도 마찬가지입니다. 이것은 기존의 다 대 다 관계에 대한 설정입니다.

기본 케이스

기본 케이스

이제 다른 테이블에 정의 된 속성 집합과 주어진 (X, Y) 쌍에 속성 P가 있어야하는 조건 집합이 있습니다. 조건 수는 고정되어 있으며 모든 쌍에 대해 동일합니다. 기본적으로 "상황 C1에서 쌍 (X1, Y1)에 속성 P1이 있음", "상황 C2에서 쌍 (X1, Y1)에 속성 P2가 있음"등이 있으며, 조인의 각 쌍에 대한 세 가지 상황 / 조건에 대해 표.

옵션 1

나의 현재 상황에서이 정확히 3 개 등의 조건은, 하나의 가능성은 열을 추가하는 것입니다 그래서, 즉 증가 할 것으로 예상 할 이유가 없다 c1_p_id, c2_p_id그리고 c3_p_idfeatx_featy주어진 위해 지정 x_id하고 y_id있는 재산, p_id세 가지 각각의 경우에 사용하기에 .

옵션 1

이것은 기능에 적용된 모든 속성을 선택하기 위해 SQL을 복잡하게 만들고 더 많은 조건으로 쉽게 확장 할 수 없기 때문에 나에게는 좋은 생각처럼 보이지 않습니다. 그러나 (X, Y) 쌍당 특정 수의 조건이 필요합니다. 실제로, 여기서 유일한 옵션입니다.

옵션 2

조건 테이블을 작성 cond하고 조인 테이블의 기본 키에 조건 ID를 추가하십시오.

옵션 2

이에 대한 한 가지 단점은 각 쌍의 조건 수를 지정하지 않는다는 것입니다. 다른 하나는 내가 초기 관계 만 고려할 때

SELECT objx.*, objy.* FROM objx
  INNER JOIN objx_objy ON objx_objy.x_id = objx.id
  INNER JOIN objy ON objy.id = objx_objy.y_id

그런 다음 DISTINCT중복 항목을 피하기 위해 절 을 추가 해야합니다. 이것은 각 쌍이 한 번만 존재해야한다는 사실을 잃어버린 것 같습니다.

옵션 3

조인 테이블에서 새 '페어 ID'를 만든 다음 첫 번째 테이블과 속성 및 조건 사이에 두 번째 링크 테이블이 있습니다.

옵션 3

이것은 각 쌍에 대해 정해진 수의 조건을 시행하지 않는 것 외에 가장 적은 단점이있는 것 같습니다. 기존 ID 이외의 다른 것을 식별하는 새 ID를 작성하는 것이 의미가 있습니까?

옵션 4 (3b)

기본적으로 옵션 3과 동일하지만 추가 ID 필드를 만들지 않습니다. 이는 새 조인 테이블에 원래 ID를 둘 다 포함 x_id하여 y_id대신에 및 필드를 포함 하여 수행 됩니다 xy_id.

옵션 4

이 양식의 또 다른 장점은 기존 테이블을 변경하지 않는다는 것입니다 (아직 프로덕션 상태는 아님). 그러나 기본적으로 전체 테이블을 여러 번 복제하거나 그런 식으로 생각하기 때문에 이상적이지 않습니다.

요약

제 느낌은 옵션 3과 4가 어느 쪽이든 갈 수있을 정도로 비슷하다는 것입니다. 속성에 대한 고정 된 작은 수의 링크가 필요하지 않다면 아마도 옵션 1이 다른 것보다 합리적으로 보일 것입니다. 매우 제한된 테스트를 기반으로 DISTINCT쿼리에 절을 추가 해도이 상황에서 성능에 영향을 미치지 않는 것 같지만 배치로 인한 본질적 중복 때문에 옵션 2가 상황과 다른 상황을 나타내는 지 확실하지 않습니다. 링크 테이블의 여러 행에서 동일한 (X, Y) 쌍.

이러한 옵션 중 하나가 최선의 방법입니까, 아니면 고려해야 할 다른 구조가 있습니까?


전반적으로 1과 4가 가장 좋은 옵션이라고 생각합니다. 옵션 4를 사용하여 고정 된 수의 속성을 적용하는 것은 쉽지 않지만 실현 가능하다고 생각합니다.
ypercubeᵀᴹ

를 들어 DISTINCT절, 내가 링크 # 2의 마지막에 하나, 같은 쿼리의 생각 xyxyc참조하지 않습니다하지만 c난 경우 ... 그래서 (x_id, y_id, c_id)제약 UNIQUE행에 (1,1,1)(1,1,2)다음 SELECT x.id, y.id FROM x JOIN xyc JOIN y, 나는 다시 동일한 두 가지를 얻을 수 있습니다 행 (1,1)(1,1).
Michael Underwood

1
그래. 어쨌든 옵션 2를 해제합니다. 나는 1 또는 4와 함께 갈 것이다.
ypercubeᵀᴹ

더 많이 생각할수록 속성 수를 정확히 3으로 제한하는 것이 요구 사항 중 가장 중요하다고 생각합니다. 따라서 다음에 추가로 건설적인 피드백을받지 않으면이 시점에서 # 4를하겠습니다. 귀하의 의견에 감사드립니다. @ypercube!
Michael Underwood

답변:


7
  • 옵션 1

    *이 기능은 모든 기능에 적용되는 모든 속성을 선택하기 위해 SQL을 복잡하게하기 때문에 나에게는 좋은 생각이 아닙니다.

    반드시 쿼리 SQL을 복잡하게 만드는 것은 아닙니다 (아래 결론 참조).

    … 더 많은 조건으로 쉽게 확장되지 않습니다…

    여전히 고정 된 수의 조건이 있고 수십 또는 수백이 아닌 한 더 많은 조건으로 쉽게 확장됩니다.

    그러나 (X, Y) 쌍당 특정 수의 조건이 필요합니다. 실제로는 이것이 유일한 옵션입니다. *

    그것은 "내 요구 사항 중 가장 중요하지 않다"고 의견을 말하지만 전혀 중요하지 않다고 말하지 않았습니다.

  • 옵션 2

    이에 대한 한 가지 단점은 각 쌍의 조건 수를 지정하지 않는다는 것입니다. 또 하나는 초기 관계 만 고려할 때… 중복 항목을 피하기 위해 DISTINCT 절을 추가해야한다는 것입니다.

    나는 당신이 언급 한 복잡한 때문에이 옵션을 해제 할 수 있다고 생각합니다. objx_objy표는 쿼리의 일부 구동 테이블 (예 : "선택 기능에 적용되는 모든 속성"나는 모든 속성을 의미 복용하고,에 적용 할 가능성이 높다 objxobjy). 뷰를 사용하여 미리 적용 할 수 DISTINCT있으므로 쿼리를 복잡하게 만들지 않아도되지만 성능이 크게 저하 되어도 거의 얻지 못합니다.

  • 옵션 3

    기존 ID 이외의 다른 것을 식별하는 새 ID를 작성하는 것이 의미가 있습니까?

    아닙니다. 옵션 4가 모든면에서 더 좋습니다.

  • 옵션 4

    … 기본적으로 전체 테이블을 여러 번 복제하거나 (그렇게 느낀다) 이상적이지 않습니다.

    이 옵션은 괜찮습니다. 속성의 수가 가변적이거나 변경 될 수있는 경우 관계를 설정하는 확실한 방법입니다

결론

각 속성의 수가 objx_objy안정적 일 가능성이 있고 소수 이상의 추가 속성을 추가 할 수없는 경우 옵션 1을 선호 합니다. 또한 'number of properties = 3'제약 조건을 적용하는 유일한 옵션입니다. 옵션 4에 대해 유사한 제약 조건을 적용 c1_p_id하려면 xy 테이블에… 열을 추가 해야합니다.

해당 조건에 대해별로 신경 쓰지 않고 속성 수의 조건이 안정적인지 의심 할만한 이유가있는 경우 옵션 4를 선택하십시오.

확실하지 않은 경우 옵션 1을 선택하십시오. 옵션이 더 간단하고 다른 사람들이 말했듯이 옵션이 있으면 더 좋습니다. 옵션 1을 해제 한 경우 "… 기능에 적용되는 모든 특성을 선택하기 위해 SQL을 복잡하게하기 때문에…"옵션 4의 추가 테이블과 동일한 데이터를 제공하는보기 작성을 제안합니다.

옵션 1 테이블 :

create table prop(id integer primary key);
create table objx(id integer primary key);
create table objy(id integer primary key);

create table objx_objy(
  x_id integer references objx
, y_id integer references objy
, c1_p_id integer not null references prop
, c2_p_id integer not null references prop
, c3_p_id integer not null references prop
, primary key (x_id, y_id)
);

insert into prop(id) select generate_series(90,99);
insert into objx(id) select generate_series(10,12);
insert into objy(id) select generate_series(20,22);

insert into objx_objy(x_id,y_id,c1_p_id,c2_p_id,c3_p_id)
select objx.id, objy.id, 90, 91, 90+floor(random()*10)
from objx cross join objy;

'에뮬레이션'옵션 4 :

create view objx_objy_prop as
select x_id
     , y_id
     , unnest(array[1,2,3]) c_id
     , unnest(array[c1_p_id,c2_p_id,c3_p_id]) p_id
from objx_objy;

"기능에 적용된 모든 속성 선택":

select distinct p_id from objx_objy_prop where x_id=10 order by p_id;

/*
|p_id|
|---:|
|  90|
|  91|
|  97|
|  98|
*/

여기 dbfiddle


-3

이러한 옵션 중 하나라도 작동 할 수 있다고 생각하지만 조건 수가 실제로 3으로 고정되어 있으면 옵션 1을 사용하고 그렇지 않으면 옵션 2를 사용합니다. Occam의 면도기는 데이터베이스 디자인에도 적용되며, 가장 단순한 디자인과 동일한 다른 모든 요소가 일반적으로 최고입니다.

엄격한 데이터베이스 정규화 규칙을 따르려면 조건 수의 고정 여부에 관계없이 2를 사용해야한다고 생각합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.