본문 바로가기

Library/Database

BCNF and 3NF

어떤 관계 스키마를 R이라 하고, R에 속하는 속성(attribute)들의 부분집합을 X라 하고, R에 속하는 어떤 속성을 A라고 하자. 이때 R에 주어진 함수 종족성들의 집합 F에 속하는 모든 FD X → A에 대해, 다음의 조건들 중 하나만 만족하는 경우, R을 제3정규형(Third Normal Form : 3NF)이라 한다.


1. A ∈ X (즉, 당연한 FD이다), 혹은
2. X는 수퍼 키, 혹은
3. A는 R의 어떤 키의 일부이다.


3NF의 정의는 BCNF와 유사한데 다른 점이라고는 세 번째 조건뿐이다. 따라서 모든 BCNF 관계 역시 3NF에도 속하게 된다. 세 번쨰 조건을 이해하려면 어떤 관계에서 키는 해당 관계를 유일하게 결정하는 속성들의 최소 집합임을 떠올리면 된다. 여기서 A는 반드시 키를 구성하는 속성이어야 한다(만약 키가 여러 개 있을 경우에는 그 중 어느 키라도 상관없다). 여기서 유의할 점은 A가 수퍼 키의 일부인 조건만으로는 불충분한데, 왜냐하면 이렇게 되면 어떤 속성이라도 이 조건을 만족할 수 있기 때문이다. 어떤 관계 스키마에서 모든 키들을 찾아내는 문제는 NP-complete라는 매우 어려운 문제로 알려져 있고, 어떤 스키마가 3NF에 속하는가를 알아내는 문제도 마찬가지이다.


어떤 함수 종속성 X → A가 3NF를 위반하는 경우는 다음 두 가지이다.

1. X는 어떤 키 K의 진부분 집합(proper subset)이다. 이러한 종속성을 부분 종속성(partial dependency)이라고도 한다. 이 경우에는 (X, A) 쌍에 대한 여러 개의 튜플들을 중복해서 저장하게 된다.

2. X는 어떤 키의 진부분 집합도 아니다. 이러한 종속성은 결국 K → X → A라고 하는 형태의 연쇄적인 종석성을 의미하기 때문에, 이를 이행 종석성(transitive dependency)이라고도 한다. 이러한 형태의 종속성에서 발생하는 문제점은 만약 어떤 X 값과 어떤 K 값을 연관시키기 위해서는, 반드시 어떤 A 값과 어떤 X 값을 역시 연관시켜 주어야 한다는 점이다.


3NF를 사용하는 이유는 다소 인위적이다. 즉, 키의 속성을 포함하는 어떤 종속성에 대해서는 예외 조항을 둠으로써, 바람직한 어떤 성질들을 준수하는 분해 알고리즘을 사용하여, 주어진 모든 릴레이션 스키마들을 3NF 관계들로 분해할 수 있음을 보장받게 된다. 그러나 이러한 보장이 BCNF 관계에서는 성립되지 않는다. 3NF의 정의는 BCNF의 제약 조건을 완화시킴으로써 이런 보장이 가능하도록 한다. 그러나, 3NF에는 BCNF와 달리 어떤 중복성이 발생할 수 있다. 즉, 만약 종속성 X → A가 존재하고 X가 수퍼키가 아니라면, 설령 A가 키의 일부이기 때문에 이 관계가 3NF에 속한다고 하더라도, 부분 종속성 및 이행 종속성에 따른 문제들이 여전히 존재하게 된다.

보이스-코드 정규형(Boyce-Codd Normal)은 다음을 만족해야 한다. 어떤 관계 스키마를 R이라 하고, R에 속하는 속성들의 부분 집합을 X라 하고, R에 속하는 어떤 속성들을 A라 했을 때, R에 주어진 FD 집합 F에 대해, FD X → A일 때, 다음 조건 중에서 하나만 만족하는 경우, 보이스-코드 정규형이라 한다.


1. A ∈ X (즉, 당연한 FD)이거나
2. X는 수퍼 키인 경우


이 정규형은 중복을 허용하지 않는다. 이것은, 제3정규형이 중복을 허용하는 것과 대비된다. 왜 제3정규형이 중복을 허용하는가? 만약, X에 해당하는 테이블이 존재하고, 나머지 R - X 집합에서 어떠한 키가 존재하지 않는다면, R - X 테이블은 데이터를 구별할 수 없게 된다. 따라서, 이런 경우에는 중복을 제거해서는 안된다. 제3정규형이 'A는 R의 어떤 키의 일부이다'라는 조건은 이것을 위한 것이다. 즉, R의 어떤 키(수퍼 키)의 일부분(후보 키)이다. 보이스-코드 정규형은 제3정규형보다 강력한 제약사항을 가지지만, 키가 깨질 수 있다는 문제점이 있고, 제3정규형은 중복을 허용한다는 문제점이 있다.

(*진부분 집합(proper subset)이란, 자기 자신을 포함하지 않는 부분집합이다. 다시 말해, A ⊆ B일 때, A ≠ B인 경우, A는 B의 진부분 집합이다)