교차 테이블을 작성하는 대신 널 입력 가능 외래 키를 사용하는 단점


15

다음과 같은 응급실 다이어그램이 있다고 가정 해보십시오.

여기에 이미지 설명을 입력하십시오

이제 Schoolin 의 외래 키를 사용하여 관계를 나타내는 경우 a 가 a 에 속할 필요가 없기 때문에 값을 Student가질 수 있습니다 .NULLStudentSchool

여기에 이미지 설명을 입력하십시오

따라서 올바른 방법은 (내가 읽은 내용을 기반으로) 관계를 나타내는 교차 테이블을 만드는 것입니다.

여기에 이미지 설명을 입력하십시오

이런 식으로 NULL테이블에 값을 표시 할 수 없습니다 School_has_Student.

그러나 교차 테이블을 생성하는 대신 널 입력 가능 외래 키를 사용하면 어떤 단점이 있습니까?


편집하다:

나는 실수로 ( school_id, student_id)를 School_has_Student테이블 의 기본 키로 선택 하여 관계를 다 대다로 만들었습니다. 올바른 기본 키는 다음과 같아야합니다 student_id.

여기에 이미지 설명을 입력하십시오


7
"올바른"방법은 없습니다. 귀하의 요구에 가장 적합한 방법이 있습니다.
MetaFight

1
나는 거짓 전제에 대해 Doc에 동의하지만 대답하기에 여전히 분명할까요?
MetaFight

잘못된 전제가 있지만 차이점을 바로 잡고 설명하는 것은 쉽습니다.

나는 가까운 투표를 철회했지만 "그래서 내가 읽은 것을 기반으로 올바른 방법은 관계를 나타내는 교차 테이블을 만드는 것" 이라는 문장 이 나에게 어떤 스트레인지 소스가 " 올바른 "방법. 이전에 읽은 모든 교과서에서 1 : n 관계에 대한 표준 방법은 단일 외래 키입니다. 아니면 뭔가 오해 했습니까?
Doc Brown

@ Doc Brown 나는 그것을 읽은 곳을 기억하지 못하지만 교차 테이블이 올바른 방법이라고 확신합니다. 어쨌든, 하나의 외래 키를 사용하여 1 : n 관계 (1 : 측면에 선택적으로 참여 함)를 표현해야한다는 책의 이름을 알려주시겠습니까?이 주제에 대해 그들이 말하는 것을 읽고 싶습니다.
Tom

답변:


18

두 모델은 서로 다른 관계를 나타냅니다.

조인 테이블을 사용하여 다 대다 관계를 모델링합니다.

간단한 외래 키를 사용하여 일대 다 관계를 모델링합니다.

널 입력 가능 외래 키의 단점은 달성하려는 경우 다 대다 관계를 모델링 할 수 없다는 것입니다.


질문에 대한 편집 내용을 바탕으로 학생용 테이블을 동일한 키를 가진 두 개의 테이블로 효과적으로 분할합니다. 나는 일반적으로 너무 많은 필드가있는 테이블에서 이것을 보았습니다. 따라서 누군가가 더 관리하기 쉽도록 두 개로 나눕니다 (돈에 립스틱을 바르는 것입니다).

학생 테이블을 분할하면 두 번째 테이블에 레코드가 없어도되므로 두 번째 테이블을 선택적으로 만들 수 있습니다. 이것은 널이 될 수 있기 때문에 설정할 필요가없는 필드와 매우 유사합니다.

일대 다 관계를 원한다면 단일 테이블을 사용하고 학생 테이블에서 학교 ID를 null로 허용하는 것이 훨씬 좋습니다. 외래 키의 경우에도 필드에서 null을 피할 이유가 없습니다. 이는 외부 관계가 선택 사항임을 나타냅니다. 개발자와 DBA는이를 명확하게 이해하고 기본 데이터베이스 엔진은 확실히 작동해야합니다.

조인이 걱정 되더라도 걱정하지 마십시오. 조인이 null 필드와 작동하는 방식에 대한 정의가 잘 정의되어 있습니다. 단일 테이블을 사용하면 3 개 대신 2 개의 테이블을 조인 할 수 있습니다.


따라서 일대 다 관계를 모델링하는 경우 (1쪽에 선택적으로 참여) NULL값 을 가질 수 있다는 사실에도 불구하고 외래 키를 사용해야 합니까?
Tom

1
@Tom 예, 정확하게 모델링하는 방법입니다. 기술적으로 조인 테이블을 사용하는 것이 가능하지만 데이터 모델은 다대 다를 허용하므로이를 방지하기 위해 트리거 및 데이터베이스 논리가 필요합니다. 잘못된 데이터를 추가 할 수없는 방식으로 관계를 제한하면 더 좋습니다.

1
내 질문을 편집했습니다. 나는 테이블 student_id에서 기본 키 만 만들었 School_has_Student으며 관계는 일대 다로 유지되었습니다. 이 방법은 외래 키를 사용하여 어떤 단점이 있습니까?
Tom

@Tom 내 답변을 편집했습니다.

6

당신은 위의 의견을 썼습니다 :

외래 키 열에 NULL 값이 많은 경우 교차 테이블을 사용하는 것이 좋습니다 (예 : 직원의 98 % 인 경우) 부서를 관리하지 마십시오)

외래 키 열에 NULL 값이 많으면 프로그램에서 처리하는 각 레코드마다이 빈 열을 처리해야합니다. 열은 모든 경우의 98 %에서 비어 있지만 일부 디스크 공간을 차지할 것입니다. 관계를 쿼리한다는 것은 해당 열을 쿼리하여 더 많은 네트워크 트래픽을 제공하고 ORM을 사용하는 경우 테이블에서 클래스를 생성하는 경우 프로그램을 의미합니다 또한 클라이언트쪽에 필요한 것보다 많은 공간이 필요합니다. 교차 테이블을 사용하면이를 피할 수 있으며, 그렇지 않으면 동등한 외래 키가 NULL이 아닌 경우 필요한 링크 레코드 만 있습니다.

반대로, NULL 값이 몇 개가 아닌 경우 50 % 이상의 관계가 NULL이 아니라고 가정하면 교차 테이블을 사용하면 디스크 공간이 많고 복잡성이 높아져 네트워크 트래픽이 증가하는 등의 반대 효과가 나타납니다.

따라서 교차 테이블을 사용하는 것은 최적화의 한 형태 일 뿐이며, 특정 경우에만, 특히 요즘에는 디스크 공간과 메모리가 저렴 해지고 훨씬 덜 자주 필요한 오늘날에만 합리적입니다. "데이터베이스 시스템의 기초"는 원래 20 년 이상 전에 작성되었으며 (1994 년부터 두 번째 버전에 대한 참조를 찾았습니다), 당시에는 권장 사항이 이미 있었다고 생각합니다. 1994 년 이전에는 대용량 스토리지가 여전히 비싸고 컴퓨터와 네트워크가 오늘날보다 훨씬 느리기 때문에 공간 최적화가 오늘날보다 훨씬 더 중요했을 것입니다.

까다로운 의견에 대한 부수적 인 설명으로, 위의 진술은 "데이터베이스 시스템의 기초"의 저자가 자신의 권장 사항을 염두에두고 생각한 것을 예상하려고 노력하고 있습니다. 일부 데이터베이스에는 교차 테이블을 사용하지 않는 "스파 스 열"과 같은 다른 최적화가 있습니다.

따라서 그 추천을 잘못하지 마십시오. 이 책은 {0,1}:n일반적으로 관계에 대한 교차 테이블을 선호 하거나, 당신이 쓴 것처럼 이것이 "올바른 방법"이라고 말하지 않습니다 . 이와 같은 최적화를 사용하면 실제로 필요할 때만 프로그램을 더 복잡하게 만들 수 있습니다.


특히 OP가 특정 데이터베이스를 언급하지 않았다는 점을 고려할 때 데이터베이스 구현에 대해 많은 것을 가정하고 있습니다. 데이터베이스가 스파 스 열에 적은 양의 공간 만 사용하기에 충분히 똑똑 할 가능성이 높습니다.
gardenhead

@gardenhead : 이것이 "가능성 이상"이라고 믿는 이유는 무엇입니까?
Doc Brown

데이터베이스는 수십 년 동안 사용되어 왔으며 대부분의 인프라에서 중요한 구성 요소이므로 고도로 최적화되어 있습니다.
gardenhead

@gardenhead : 당신은 나보다 훨씬 무의미한 가정을 만들고 있다고 들었습니다. 그럼에도 불구하고 내 편집을 참조하십시오.
Doc Brown

2

개념 모델 인이, 모양을 매우 정통 덜 말 :

여기에 이미지 설명을 입력하십시오

실제 모델은 다음과 같이 보일 것이며 , 덜 말하면 혼란 스러울 것입니다.

여기에 이미지 설명을 입력하십시오

나의 제안:

대부분의 학생들에게 적용되지 않는 많은 열 (FK 또는 기타)이있는 경우 테이블을 1 : 1 관계로 역할 테이블로 분리하십시오. 그러나 이는 FK이기 때문에 열이 대부분의 행에 적용되지 않기 때문입니다.

그렇지 않으면 , 널 (NULL) FK는 데이터베이스의 정상적인 일부이며 테이블이 M에 대한 보통 가입 : M의 RELS.

1 : 1 관계의 일반적인 용도는 엔터티가 특정 유형 인 경우에만 적용되는 열이 있고 성능 또는 저장소 고려 사항에 대한 BLOB 열을 추출하는 역할 테이블에 사용됩니다. FK에서 널값을 피하는 것은 일반적인 사용법이 아닙니다.

여기에 이미지 설명을 입력하십시오


2

다른 답변 외에도 외래 키의 null 값이 모호하다는 것을 지적하고 싶습니다. 그것은 의미합니까?

1) 학생의 학교 (있는 경우)를 알 수없는 경우 ( 'null'의 표준 의미-값을 알 수 없음)

2) 학생이 학교를 가지고 있는지 여부를 알고 있으며, 학교가 없다

null의 표준 의미를 사용하는 경우 외래 키 모델에서 "학생은 학교가 없습니다"를 어떻게 표현합니까? 이 경우, 학교 테이블에 ID가있는 "학교 없음"항목을 ​​작성해야합니다. (이상적이지 않음)


2
"데이터베이스 시스템의 기초" 책 은에 대한 3 가지 해석이 NULL있으며 다음을 의미 할 수 있습니다. 1) 알 수없는 값. 2) 사용할 수 없거나 보류 된 가치. 3) 해당 사항 없음 속성 (이 해석은 NULL외래 키에 대해를 지정할 수 있음을 의미한다고 생각합니다 ).
Tom

1
유용한 목록이지만 null의 의미 (또는 실제 값)는 사용자가 정의 할 수 있습니다. 즉, 디자이너가 말한 모든 것을 의미 할 수 있습니다 (해당 목록에만 국한되지 않음). 문제는 둘 이상이 필요할 때 (또는 실수로 저장 한 경우) 다른 의미를 구별하는 방법입니다.
Brad Thomas

따라서 nullable 외래 키를 사용하는 대신 교차 테이블을 만들어야한다고 제안합니까?
Tom

@Tom 네, 저는이 경우에 더 낫다고 믿습니다
Brad Thomas

@BradThomas-교차 테이블을 사용할 때 동일한 모호성을 피하려면 NULL School_ID를 사용하여 교차 테이블의 레코드로 사례 2 (학생이 학교가 없음을 알고 있음)를 나타내시겠습니까?
앤드류

1

데이터베이스 테이블에는 제약 조건이라는 멋진 기능이 있습니다. 따라서 각 학생 중 1 명만 테이블에 표시 할 수있는 교차 테이블에서 테이블을 만드는 것이 매우 쉽습니다. 효과적으로 당신에게주는

이론은 훌륭하지만 결국 질문을 한 후에 데이터베이스를 모델링 할 것입니다.

"내 학생들이 어느 학교에 있는지"라는 질문으로 자주 질문하고 싶다면 전체 학생 테이블을 쿼리하거나 쉬운 교차 테이블을 원하십니까?

데이터베이스에서 : 질문에 최적화하십시오.


0

세 번째 테이블을 사용하는 것이 실제로 의미가있는 사용 사례가 있습니다. 이 예는 순전히 가상적인 것처럼 보일 수 있지만, 그것이 나의 요점을 잘 설명해주기를 바랍니다. students테이블 에 더 많은 열을 추가한다고 가정 하고 어느 시점에서 여러 열의 복합 인덱스를 통해 레코드에 고유성을 적용하기로 결정했습니다. school_id열 을 포함해야 할 가능성이 매우 높으며 여기에서 문제가 발생하기 시작합니다. 방식 때문에 SQL은 여러 동일한 레코드를 삽입, 디자인 된 school_id이다가 NULL가능한 것입니다. 기술적 인 관점에서는 완벽하게 이해되지만, 직관적이지 않으며 예기치 않은 결과가 발생할 수 있습니다. 반면, 교차 테이블에서 고유성을 적용하는 것은 쉽습니다.

유일성 제약 조건이 타임 스탬프 열로 인해 발생한 "선택적"관계를 최근에 모델링해야했습니다. 테이블에 널 입력 가능 외래 키를 남겨두면 갑자기 동일한 타임 스탬프를 가진 레코드를 삽입 할 가능성이 생깁니다 (아직 감사하고 승인되지 않은 레코드에 설정된 기본 설정이라고 가정). 널 입력 가능 열.

보시다시피, 이것은 상당히 구체적인 경우이며 다른 사람들이 언급했듯이 대부분의 경우 모든 NULL값을 완벽하게 사용할 수 있습니다 . 모델의 특정 요구 사항에 따라 다릅니다.


0

이미 제출 된 많은 좋은 제안 외에도 개인적으로 나는 정말로 필요한 경우가 아니라면 외래 키의 팬이 아닙니다. 먼저 참조하는 M : M 관계가 있습니다. 또한 외래 키를 호출하여 해당 테이블 데이터를 쿼리로 가져 오면 테이블 크기에 따라 성능이 저하되고 복잡성이 증가합니다. 다른 사람들이 말했듯이, nullable FK 필드는 지원되지 않을 수 있으며 데이터 무결성 문제를 일으킬 수 있습니다.

학생 학교를 알 수 없거나 비어있는 주를 정의하는 경우 NULL은 이러한 조건을 구별하지 않습니다. (우리는 다시 데이터 무결성으로 돌아 왔습니다.) Tulains의 역할 테이블 제안은 우아하며 null 값을 깔끔하게 허용합니다.

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