출처 : 데이터베이스 개론
E-R 모델을 사용해 개념적인 설계를, 그리고 E-R 모델을 릴레이션 스키마로 변환하는 과정을 통해 데이터베이스의 논리적인 설계에 대해 배울 수 있었다. 논리적인 설계를 하는 방법에는 E-R 모델을 변환하는 것만 존재하는게 아니다. 정규화를 사용해서도 논리적인 설계를 진행할 수 있다. E-R 모델 변환과 정규화를 통해 만들어지는 릴레이션 스키마는 대동소이 하기 때문에 각자 상황에 맞는 방식으로 데이터베이스 설계를 진행하면 된다.
또한, 정규화는 릴레이션 스키마를 만드는 것만이 아니라 생성된 릴레이션 스키마를 검증하기 위해서도 사용할 수 있다. 데이터베이스 설계가 잘못되었을 경우, 불필요한 데이터가 같은 릴레이션에 포함되어 중복 문제가 발생할 수 있다. 이를 이상 현상이라 부르는데, 정규화는 이 이상 현상을 제거하여 올바른 방향으로 데이터베이스를 설계할 수 있도록 도와주는 역할을 하는 것이다.
9.1 이상 현상(anomaly)의 종류
- 삽입 이상 : 새 데이터를 삽입하기 위해 불필요한 데이터도 함께 삽입해야 하는 문제
- 갱신 이상 : 중복 투플 중 일부만 변경하여 데이터가 불일치하게 되는 모순의 문제
- 삭제 이상 : 투플을 삭제하면 꼭 필요한 데이터까지 함께 삭제되는 데이터 손실의 문제
삽입, 갱신, 삭제는 잘못 설계된 데이터베이스에서 발생하는 대표적인 이상 현상이다. 구체적으로 어떤 상황에서 이상 현상이 발생하는지 확인해보자.
이벤트참여 릴레이션
고객아이디(PK) | 이벤트번호(PK) | 당첨여부 | 고객이름 | 등급 |
---|---|---|---|---|
apple | E001 | Y | 정소화 | gold |
apple | E005 | N | 정소화 | gold |
apple | E010 | Y | 정소화 | gold |
banana | E002 | N | 김선우 | vip |
banana | E005 | Y | 김선우 | vip |
carrot | E003 | Y | 고명석 | gold |
carrot | E007 | Y | 고명석 | gold |
orange | E004 | N | 김용욱 | silver |
이벤트참여 릴레이션은 이벤트에 참여한 고객의 정보를 저장하고 있는 릴레이션이다. 한 고객이 여러 이벤트에 참여할 수 있기 때문에 고객아이디만으론 투플을 식별할 수 없기 때문에 고객아이디 - 이벤트번호를 합친 복합키를 PK로 사용하고 있다.
고객 한 명이 여러 이벤트에 참여할 수 있기 때문에, 현재 이벤트참여 릴레이션에는 고객아이디와 고객이름이 중복해서 나타나고 있다.
- 고객아이디가
apple
인 고객은 E001, E005, E010 이벤트에 참여했기 때문에 세 개의 투플을 가지고 있다.
고객아이디 - 이벤트번호 복합키를 기본키로 사용하고 있지만, 같은 고객이 여러 번 이벤트에 참여하면 불필요한 데이터 저장이 발생해 저장 공간을 낭비하고 릴레이션에 데이터를 삽입, 수정, 삭제할 때 이상 현상이 발생할 수 있기 때문에 이러한 중복을 최대한 줄일 필요가 있다. 이제 이벤트참여 릴레이션에 이상 현상을 일으켜 볼 시간이다.
삽입 이상
삽입 이상은 릴레이션에 새 데이터를 삽입하기 위해 원하지 않는 데이터도 함께 삽입해야 하는 상황을 의미한다. 이벤트참여 릴레이션에서 한 명의 고객이 여러 이벤트에 참여할 수 있기 때문에 고객을 식별하는 고객아이디는 이벤트참여 릴레이션의 기본키로 사용할 수 없다. 그래서 이벤트번호를 묶은 복합키를 기본키로 사용하는데, 이로 인해 삽입 이상이 발생할 수 있다.
고객아이디(PK) | 이벤트번호(PK) | 당첨여부 | 고객이름 | 등급 |
---|---|---|---|---|
melon | NULL | NULL | 성완용 | gold |
고객아이디가 melon, 고객이름이 성완용, 등급이 gold인 신규 고객이 추가되었다고 가정해보자. 이 상황에서 이벤트참여 릴레이션에 해당 고객의 정보를 추가하고 싶지만, 참여한 이벤트가 없는 상태라면 이벤트번호와 당첨여부 속성에는 NULL이 들어가게 될 것이다. 하지만 기본키를 구성하는 속성은 NULL을 가질 수 없다는 제약이 존재하기 때문에 성완용 고객에 대한 데이터를 이벤트참여 릴레이션에 추가하기 위해선 임의의 이벤트번호를 생성해서 삽입을 진행해야 한다.
이와 같이 특정 릴레이션에 새로운 데이터를 삽입하고자 할 때, 원하지 않는 데이터도 함께 삽입을 해야하는 경우를 삽입 이상이라고 한다.
갱신 이상
갱신 이상은 중복된 속성값을 가지는 투플들 중 일부만 수정했을 때, 나머지 데이터와의 데이터 정합성이 깨지게 되는 모순이 발생하는 경우를 의미한다. 이벤트참여 릴레이션에는 여러 이벤트에 참여한 고객들이 존재한다. 그 중에서 apple
이라는 고객 아이디를 사용하는 고객에 대한 투플은 총 세 개가 존재하며, 고객아이디와 고객이름, 등급 속성이 중복되어 있는 것을 볼 수 있다.
고객아이디(PK) | 이벤트번호(PK) | 당첨여부 | 고객이름 | 등급 |
---|---|---|---|---|
apple | E001 | Y | 정소화 | gold |
apple | E005 | N | 정소화 | gold |
apple | E010 | Y | 정소화 | gold |
이 상황에서 고객의 등급이 gold에서 vip로 변경이 된다면, 이벤트참여 릴레이션에 존재하는 투플 세 개의 등급 속성값을 모두 수정해야 한다. 하나 또는 두개의 투플만 수정을 하게 되면 모순이 발생하고, 이는 곧 갱신 이상이라 할 수 있다.
삭제 이상
삭제 이상은 투플을 삭제할 때, 꼭 필요한 데이터까지 함께 삭제가 되어 데이터 손실이 발생하고, 이로 인해 다른 데이터도 함께 삭제되는 연쇄 삭제 현상을 의미한다.
고객아이디(PK) | 이벤트번호(PK) | 당첨여부 | 고객이름 | 등급 |
---|---|---|---|---|
orange | E004 | N | 김용욱 | silver |
고객아이디가 orange인 고객이 이벤트 E004에 참여를 했다. 그러나 이벤트 참여를 취소하게 되면 이벤트참여 릴레이션에서 해당 고객의 정보를 삭제해야 한다. 다행히 orange 고객이 참여한 이벤트가 하나 밖에 존재하지 않아 해당 투플을 삭제를 했다.
여기서 바로 삭제 이상 현상이 발생했다. 우리에게 필요한 정보는 고객아이디가 orange인 고객이 이벤트참여를 취소 했다는 정보이다. 그러나 이벤트참여 릴레이션에서 orange 고객의 정보를 삭제해버리면, 이벤트참여 여부에 대한 정보 외에도 고객아이디, 고객이름, 등급과 같이 이벤트참여에 대한 정보 외에도 고객에 대한 정보도 함께 삭제가 된다. 즉, 이벤트참여를 취소하면서 이벤트참여에 대한 정보와 함께 고객 정보도 함께 삭제된 것이다.
정규화의 필요성
이벤트참여 릴레이션은 삽입, 갱신, 삭제 이상이 모두 발생할 가능성을 가지고 있다. 그 이유는 이벤트참여 릴레이션 하나에 서로 관련이 없는 데이터를 모아두고 있기 때문이다. 이상 현상 발생을 막는 방법은 하나의 릴레이션에는 서로 관련 있는 속성들만 가지고 있어야 한다. 그리고 이를 위해 필요한 것이 바로 정규화이다.
정규화를 통해 릴레이션을 만들 수도 있지만, 만들어진 릴레이션을 정규화를 통해 검증하는 것이 필요한 이유라 할 수 있다. 이벤트참여 릴레이션의 경우와 같이 서로 관련이 없는 데이터가 모여있으면, 정규화를 통해 릴레이션을 분해하고 서로 관련이 있는 데이터끼리 모이게 할 수 있다.
정규화를 위해서는 릴레이션을 구성하는 속성들 사이의 관련성을 판단해야 한다. 정규화 과정에서 고려해야 하는 속성 사이의 관련성을 함수적 종속성이라 하는데, 릴레이션에 함수적 종속성이 하나 존재하도록 정규화를 진행하게 된다. 이제 정규화를 위해 함수적 종속성이 무엇인지 알아볼 차례이다.
9.2 함수 종속
하나의 릴레이션을 구성하는 속성들의 부분 집합을 X와 Y라 할 때, 어느 시점에서든 릴레이션 내의 모든 투플을 대상으로 한 X 값에 대한 Y 값이 항상 하나인 경우, X가 Y를 함수적으로 결정한다
또는 Y가 X에 대해 함수적으로 종속되어 있다
라고 한다. 함수 종속 관계는 X -> Y
로 표현하고 X를 결정자, Y를 종속자라고 한다.
간단한 릴레이션으로 함수 종속 관계를 판단해보자.
고객 릴레이션
고객아이디(PK) | 고객이름 | 등급 |
---|---|---|
apple | 정소화 | gold |
banana | 김선우 | vip |
carrot | 고명석 | gold |
orange | 김용욱 | silver |
고객아이디는 고객 릴레이션의 기본키이다. 함수 종속 관계는 X -> Y
로 표현할 수 있는데, 기본키인 고객아이디를 X라고 생각해보자. X가 apple
인 경우에 고객이름과 등급은 항상 하나의 값을 가지게 된다. 마찬가지로 고객아이디가 banana
, carrot
, orange
인 경우에도 고객이름과 등급은 항상 하나의 값을 가진다.
이런 경우 고객이름과 등급 속성은 고객아이디 속성에 대해 함수적으로 종속되어 있다고 볼 수 있으며, 같은 의미로 고객아이디가 고객이름과 등급을 함수적으로 결정한다고 볼 수 있다. 이를 표현하면 다음과 같다.
고객아이디 -> 고객이름
고객아이디 -> 등급
or
고객아이디 -> (고객이름, 등급)
결과적으로 고객 릴레이션의 기본키인 고객아이디를 통해서 다른 속성들을 함수적으로 결정할 수 있고, 이는 기본키를 통해 다른 투플을 식별할 수 있다는 의미와 비슷하게 느껴지기도 한다. 주의해야 할 점은 함수 종속 관계는 현재 릴레이션에 삽입된 데이터만으로 판단하면 안 된다는 부분이다. 릴레이션의 스키마는 쉽게 변하지 않지만, 투플은 삽입과 삭제가 빈번히 발생하기 때문에 항상 같은 속성값들을 가지고 있지 않기 때문이다. 그래서 함수 종속 관계를 판단할 때에는 릴레이션의 속성 자체가 가지고 있는 특성과 의미를 기반으로 판단을 해야 한다.
고객 릴레이션의 함수 종속 관계를 보자. 기본키인 고객아이디는 고객 릴레이션에서 다른 투플을 식별할 수 있는 유일한 특성을 가지고 있다. 따라서 특정 고객아이디가 정해지면, 그 아이디에 해당하는 유일한 고객이름과 등급 속성값을 가질 수 있게 된다. 이는 고객아이디가 고객이름, 등급 속성을 결정하는 것이라 표현할 수도 있으며, 고객아이디가 고객이름, 등급을 함수적으로 결정한다는 의미와 같다.
위에서 살펴본 것과 같이 기본키와 후보키는 다른 투플을 구별할 수 있는 유일한 특성을 가지기 때문에 릴레이션의 다른 속성들을 함수적으로 결정하게 된다. 하지만 기본키나 후보키만이 결정자가 될 수 있는 것은 아니다. 다른 일반적인 속성이라도 X가 Y 값을 유일하게 결정하는 함수 종속의 특성만 가지고 있다면 결정자가 될 수 있다.
이벤트참여 릴레이션
고객아이디(PK) | 이벤트번호(PK) | 당첨여부 | 고객이름 |
---|---|---|---|
apple | E001 | Y | 정소화 |
apple | E005 | N | 정소화 |
apple | E010 | Y | 정소화 |
banana | E002 | N | 김선우 |
banana | E005 | Y | 김선우 |
carrot | E003 | Y | 고명석 |
carrot | E007 | Y | 고명석 |
orange | E004 | N | 김용욱 |
고객등급 속성이 삭제된 이벤트참여 릴레이션이다.
이 릴레이션에서 고객아이디는 고객이름을 함수적으로 결정한다. 고객아이디가 apple
이라면 고객이름은 항상 정소화
가 된다. 이는 다른 모든 고객아이디의 값에서도 동일하게 적용된다. 따라서 고객이름은 고객아이디에 함수적으로 종속되어 있다고 볼 수 있다.(고객아이디 -> 고객이름
)
이벤트참여 릴레이션에서는 한 명의 고객이 여러 이벤트에 참여할 수 있기 때문에 고객아이디 - 이벤트번호 복합키를 기본키로 사용할 수 있다. 고객아이디 - 이벤트번호는 당첨여부를 유일하게 식별할 수 있는 결정자로 사용할 수 있다.(고객아이디 - 이벤트번호 -> 당첨여부
) 동시에 고객이름도 기본키인 고객아이디 - 이벤트번호에 함수적으로 종속되어 있다.(고객아이디 - 이벤트번호 -> 고객이름
)
고객아이디 -> 고객이름
고객아이디 - 이벤트번호 -> 당첨여부
고객아이디 - 이벤트번호 -> 고객이름
이벤트참여 릴레이션에는 위와 같은 함수 종속 관계가 존재한다. 그런데 고객이름 속성은 고객아이디에도 종속되어 있지만, 고객아이디 - 이벤트번호에도 종속되어 있다. 이 경우 고객이름 속성은 부분 함수 종속되어 있다고 하는데, 반대로 당첨여부와 같이 고객아이디 - 이벤트번호 하나에만 종속되어 있는 경우를 완전 함수 종속되어 있다고 한다.
완전 함수 종속은 릴레이션에서 종속자 Y가 결정자 X에 함수적으로 종속되어 있지만, 결정자 X의 전체가 아닌 일부에는 종속되지 않음을 의미한다.(복합키를 사용할 때, 복합키의 부분 집합에는 종속되지 않고, 복합키를 구성하는 모든 속성에 대해 종속되어야 함.)
반대로 부분 함수 종속은 종속자 Y가 결정자 X에 함수적으로 종속되어 있지만, 결정자 X의 일부에도 함수적으로 종속되었음을 의미한다.(복합키를 사용할 때, 복합키의 부분 집합에도 종속됨.)
일반적인 경우 함수 종속은 완전 함수 종속을 의미하지만, 정규화를 수행하는 과정 중에 릴레이션이 부분 함수 종속 관계를 포함하고 있는지를 확인하는 경우가 있으므로 부분 함수 종속도 정확한 의미를 알고 있어야 한다.
9.3 기본 정규형과 정규화 과정
이제 정규화가 어떤 개념인지 알게 됐다. 함수 종속성을 이용해 릴레이션을 서로 연관성이 있는 속성들로만 구성하게 만들어 이상 현상 발생을 방지하는 행위를 정규화라고 하는데, 이제 어떻게 정규화를 하는지 알아 볼 차례이다.
정규화는 기본 정규형과 고급 정규형으로 나누어지는데, 각 정규형마다 만족시켜야 하는 제약조건이 존재한다. 그리고 릴레이션이 각 정규형의 제약조건을 만족하면 그 릴레이션은 해당 정규형에 속한다고 표현한다. 정규형의 차수가 높아질수록 요구되는 제약조건이 많아지고 엄격해지며, 데이터 중복이 줄어 이상 현상이 발생하지 않는 이상적인 릴레이션이 된다.
제 1 정규형
릴레이션에 속한 모든 속성의 도메인이 원자 값(atomic value)으로만 구성되어 있으면 제 1 정규형에 속한다.
제 1 정규형의 조건은 릴레이션에 속한 모든 속성의 값이 원자 값을 가져야 하는 것이다. 원자 값은 더는 분해되지 않는 값을 의미한다.
이벤트참여 릴레이션
고객아이디(PK) | 이벤트번호(PK) | 당첨여부 | 등급 | 할인율 |
---|---|---|---|---|
apple | E001, E005, E010 | Y,N,Y | gold | 10% |
이벤트참여 릴레이션의 이벤트번호와 당첨여부 속성에는 여러 값이 들어가 있다. 제 1 정규형 조건을 충족시키려면 모든 속성의 값이 원자 값이 되어야 하기 때문에 다음과 같이 정규화를 진행해주어야 한다.
고객아이디(PK) | 이벤트번호(PK) | 당첨여부 | 등급 | 할인율 |
---|---|---|---|---|
apple | E001 | Y | gold | 10% |
apple | E005 | N | gold | 10% |
apple | E010 | Y | gold | 10% |
이제 이벤트참여 릴레이션은 제 1 정규형을 만족하게 됐다. 하지만 이상 현상이 충분히 발생할 수 있다. 이벤트참여 릴레이션에서 어떤 이상 현상이 발생할지 파악해보기 위해 함수 종속 관계를 파악해보자.
- 고객아이디 - 이벤트번호 복합키를 기본키로 사용
- 고객 한 명이 하나의 등급과 할인율을 가짐
- 고객아이디로 등급과 할인율을 식별할 수 있음
- 등급으로 할인율을 식별할 수 있음
- 고객아이디 - 이벤트번호를 통해 당첨여부를 식별할 수 있음
고객아이디 - 이벤트번호 => 당첨여부
고객아이디 -> 등급, 할인율
등급 -> 할인율
얼핏보기에도 기본키에 해당하는 속성에만 함수 종속 관계가 나타나지 않고, 일반 속성에도 함수 종속 관계가 나타난 것을 확인할 수 있다. 여기에 등급과 할인율 속성의 값이 중복되어 나타나고 있기도 하다. 현재 상황에서는 이벤트참여 릴레이션에서 다음과 같은 이상 현상이 발생할 수 있을 것이다.
- 삽입 이상 : 이벤트에 참여하지 않은 새로운 고객 데이터가 삽입 될 경우, 이벤트번호 속성이 NULL이 되어 개체 무결성 제약조건을 위반하게 된다.
- 갱신 이상 : 등급이 gold에서 silver로 변경되면 할인율이 변하게 된다. 이벤트참여 릴레이션에서 해당 회원의 등급을 모든 투플에 대해 갱신하지 않으면 모순이 발생한다.
- 삭제 이상 : 고객이 이벤트에 참여한 기록을 삭제하면 이벤트번호, 당첨여부와 같이 이벤트와 관련된 속성들 뿐만 아니라 고객아이디, 등급, 할인율과 같은 고객과 관련된 속성들도 함께 삭제된다. 고객의 정보를 유지할 수 없게 된다.
이벤트참여 릴레이션은 제 1 정규화를 진행했지만, 이상 현상을 피할 순 없었다. 이는 이벤트참여 릴레이션이 부분 함수 종속성을 가지고 있기 때문이다. 이벤트참여 릴레이션은 기본키로 고객아이디 - 이벤트번호로 구성된 복합키를 사용하고 있는데, 고객아이디로 등급과 할인율을 결정할 수 있고, 등급이 할인율을 결정할 수 있는 상황이다. 또한, 등급과 할인율 속성에 같은 값이 여러 번 나타나고 있으며 고객과 관련이 없는 이벤트번호와 당첨여부도 같은 릴레이션에 존재하고 있다.
제 2 정규형
릴레이션이 제 1 정규형에 속하고, 기본키가 아닌 모든 속성이 기본키에 완전 함수 종속되면 제 2 정규형에 속한다.
제 2 정규형은 부분 함수 종속을 제거하고, 모든 속성이 기본키에 완전 함수 종속되도록 릴레이션을 분해하는 정규화 과정이다. 이벤트참여 릴레이션에는 기본키에만 다른 속성들이 종속되어 있지 않은 부분 함수 종속을 가지고 있다.
고객에 대한 정보인 등급과 할인율을 이벤트참여 릴레이션이 아닌 고객 릴레이션으로 분해해서 부분 함수 종속을 제거해보자.
고객 릴레이션
고객아이디(PK) | 등급 | 할인율 |
---|---|---|
apple | gold | 10% |
이벤트참여 릴레이션
고객아이디(PK) | 이벤트번호(PK) | 당첨여부 |
---|---|---|
apple | E001 | Y |
apple | E005 | N |
apple | E010 | Y |
이벤트참여 릴레이션 하나에서 고객과 이벤트에 대한 정보를 가지고 있었기 때문에 서로 관련이 없는 데이터가 뭉쳐 있었다. 그래서 이를 고객에 대한 정보를 저장하는 고객 릴레이션과 이벤트에 대한 정보를 저장하는 이벤트참여 릴레이션으로 분해하여 부분 함수 종속을 제거한다.
이제 고객 릴레이션에서는 고객아이디로 등급과 할인율을 식별할 수 있고, 이벤트참여 릴레이션에서는 고객아이디 - 이벤트번호를 사용해서 당첨여부를 식별할 수 있다. 문제가 되었던 고객아이디 - 이벤트번호 복합키의 부분 속성이 다른 속성을 결정하고 있지 않게 된 것이다.
고객 릴레이션과 이벤트참여 릴레이션에서 부분 함수 종속이 제거 되었지만, 아직 문제가 남아 있다. 고객 릴레이션의 등급 속성이 할인율을 결정하고 있기 때문이다. 등급이 기본키의 부분 집합이 아니기 때문에 부분 함수 종속이 아닌 일반적인 함수 종속이 남아 있는 상황이기에 하나의 릴레이션에 여러 함수 종속성이 존재하고 있어 이상 현상이 발생할 가능성이 있다는 것이다.
고객 릴레이션에서 발생할 수 있는 이상 현상은 다음과 같다.
- 삽입 이상 : 새로운 등급이 추가되는 경우, 고객 릴레이션에 새로운 등급을 단독으로 추가할 수 없다. 이는 등급과 할인율이 고객아이디에 종속되어 있기 때문이다. 새로운 등급을 단독으로 삽입하면 기본키인 고객아이디가 NULL이 되어 개체 무결정 제약조건을 위반한다.
- 갱신 이상 : 등급에 대한 할인율이 변경되는 경우, 고객 릴레이션에 존재하는 모든 투플의 할인율을 함께 변경해주어야만 한다. 그렇지 않으면 같은 등급이 서로 다른 할인율을 가지는 모순이 발생하기 때문이다.
- 삭제 이상 : 고객이 탈퇴하여 데이터가 제거되는 경우, 등급과 할인율에 대한 정보도 함께 삭제된다.
이는 고객 릴레이션에 등급과 할인율 사이에 존재하는 함수 종속 관계 때문에 발생한 이행적 함수 종속 때문이다.
제 3 정규형
릴레이션이 제 2 정규형에 속하고, 기본키가 아닌 모든 속성이 기본키에 이행적 함수 종속이 되지 않으면 제 3 정규형에 속한다.
제 3 정규형에서는 릴레이션 내에 존재하는 이행적 함수 종속을 제거하여 정규화를 진행한다. 이를 위해 이행적 함수 종속에 대해 알아 볼 필요가 있다. 릴레이션을 구성하는 세 개의 속성 집합 X, Y, Z에 대해 함수 종속 관계가 X -> Y
, Y -> Z
로 존재하고 있다면, 논리적으로는 X -> Z
가 성립한다. 이런 경우를 집합 Z가 X에 이행적으로 함수 종속되었다고 한다.
제 2 정규형을 통해 부분 함수 종속을 제거하더라도 고객 릴레이션에서처럼 이행적 함수 종속이 발생할 수 있다. 고객 릴레이션은 기본키인 고객아이디가 등급을 결정하고, 다시 등급이 할인율을 결정하는 이행적 함수 종속이 존재하고 있다. 고객 릴레이션만 보면 고객아이디가 할인율을 식별한다고 보이기도 하지만, 실상은 등급이 할인율을 결정하기 때문에 고객아이디 -> 등급
, 등급 -> 할인율
이라는 관계가 성립하고 고객아이디 -> 할인율
이라는 이행적 종속 관계가 발생하게 되는 것이다.
이행적 함수 종속이 존재하는 이유는 함수 종속 관계가 하나의 릴레이션에 여러 개 존재하기 때문이다. 그래서 이행적 함수 종속을 제거하는 방법 역시 릴레이션의 분해가 된다. X -> Y
, Y -> Z
의 이행적 종속 관계가 발생했다면, 종속의 의미는 유지하면서 분해를 진행하는 것이 좋다. 그래야 각자 의미가 있는 데이터의 집합으로 만들 수 있기 때문이다.
이를 고객 릴레이션에 적용하면 다음과 같이 나타낼 수 있다.
고객 릴레이션
고객아이디(PK) | 등급 |
---|---|
apple | gold |
고객등급 릴레이션
등급(PK) | 할인율 |
---|---|
gold | 10% |
고객아이디 -> 등급
, 등급 -> 할인율
이라는 종속 관계로 인해 이행적 함수 종속이 발생했기 때문에, 각 종속 관계의 의미를 살리고, 서로 연관 있는 데이터끼리 묶는다면 고객 릴레이션을 고객과 고객등급 릴레이션으로 분해할 수 있다. 이렇게 해서 분해된 각 릴레이션에 이행적 함수 종속이 제거되어 제 3 정규형을 만족시킬 수 있게 됐다.
보이스/코드 정규형
릴레이션의 함수 종속 관계에서 모든 결정자가 후보키이면 보이스/코드 정규형에 속한다.
하나의 릴레이션에 여러 후보키가 존재할 수 있는데, 이 경우 제 3 정규형까지 만족하더라도 이상 현상이 발생할 수 있다. 후보키를 여러 개 가지고 있는 릴레이션에 발생할 수 있는 이상 현상을 해결하기 위해 제 3 정규형보다 엄격한 제약조건을 제시한 것이 바로 보이스/코드 정규형이다.
따라서 보이스/코드 정규형에 속하는 모든 릴레이션은 제 3 정규형에 속하지만, 제 3 정규형에 속하는 릴레이션이라고 해서 보이스/코드 정규형을 만족시킨다는 보장이 없기 때문에 강한 제 3 정규형이라고도 표현한다.
위에서 살펴본 고객 릴레이션, 이벤트참여 릴레이션은 기본키로 사용되는 속성이 유일한 후보키이기 때문에 모든 결정자가 후보키가 되는 보이스/코드 정규형을 만족한다고 할 수 있다. 하지만 다음의 릴레이션은 조금 다르다.
강좌신청 릴레이션
고객아이디(PK) | 인터넷강좌(PK) | 담당강사번호 |
---|---|---|
apple | 영어회화 | P001 |
banana | 기초토익 | P002 |
carrot | 영어회화 | P001 |
orange | 영어회화 | P003 |
강좌신청 릴레이션은 고객아이디와 인터넷강좌 복합키를 기본키로 사용하여 담당강사번호 속성을 식별하고 있다. 여기서 강좌신청 릴레이션의 특성을 확인해야 한다. 강사는 하나의 인터넷강좌만 담당할 수 있으며, 하나의 인터넷강좌는 여러 강사가 담당할 수 있다.
따라서 고객아이디 - 인터넷강좌를 통해 어떤 담당강사가 있는지 식별할 수 있으며, 동시에 담당강사번호 - 고객아이디를 통해 인터넷강좌를 식별할 수도 있다. 또한, 강사는 하나의 인터넷강좌만 담당하기 때문에 담당강사번호가 인터넷강좌를 식별할 수도 있다.
이렇게 투플을 식별할 수 있는 후보키가 두 개가 존재하는 상황에서 현재는 고객아이디 - 인터넷강좌를 기본키로 선택한 상황이다. 강좌신청 릴레이션은 모든 속성이 원자 값이기 때문에 제 1 정규형을 만족하며, 기본키인 고객아이디 - 인터넷강좌에 담당강사번호가 완전 함수 종속 관계를 가지고 있어 제 2 정규형 역시 만족하고 있다. 여기에 이행적 함수 종속 관계도 없기 때문에 제 3 정규형 역시 만족하고 있다.
하지만 담당강사번호 속성은 단독으로 후보키로 사용될 수 없지만 담당강사번호 -> 인터넷강좌
라는 함수 종속 관계를 결정하는 결정자 역할을 하고 있기 때문에 보이스/코드 정규형은 만족하지 않고 있다. 보이스/코드 정규형을 만족하지 못 해 발생할 수 있는 이상 현상을 살펴보자.
- 삽입 이상 : 새로운 강사가 인터넷강좌를 개설해도, 신청한 고객이 없다면 강좌신청 릴레이션에 추가할 수 없다. 고객아이디 - 인터넷강좌가 기본키이기 때문에 강제로 삽입하면 고객아이디가 NULL이 되어 개체 무결정 제약조건을 위반하게 된다.
- 갱신 이상 : 특정 강사가 담당하는 인터넷강좌가 변경되면, 강좌신청 릴레이션에서 해당 강사의 모든 인터넷강좌 속성을 갱신해주어야 한다. 그렇지 않을 경우, 강사가 담당하는 인터넷강좌가 서로 일치하지 않는 모순이 발생하게 된다.
- 삭제 이상 : 고객이 인터넷강좌의 신청을 취소하여 데이터를 제거해야 하는 경우, 연관된 인터넷 강좌, 담당강사번호 속성이 삭제 된다. 고객을 삭제하면서 강좌와 강사에 대한 데이터가 함께 삭제된다.
제 3 정규형까지 만족했음에도 불구하고 하나의 릴레이션에 여러 함수 종속 관계가 존재하여 이상 현상이 발생하고 있음을 확인했다. 부분 함수 종속, 이행적 함수 종속이 없는 상태에서도 후보키가 아닌 다른 속성이 결정자 역할을 하면서 이런 문제가 발생했기 때문에 릴레이션을 분해하여 후보키만이 결정자가 될 수 있도록 만들어야 한다.
강좌신청 릴레이션에는 고객아이디 - 인터넷강좌, 담당강사번호 - 고객아이디 총 두 개의 후보키가 존재했다. 여기에 강사를 통해 인터넷강좌를 식별할 수 있다는 특성을 생각하여 담당강사번호 - 고객아이디를 기본키로 하는 새로운 릴레이션을 만들고, 해당 강사가 담당하는 강좌에 대한 데이터를 저장하는 신규 릴레이션을 추가하는 형식으로 후보키만으로 결정자가 될 수 있게 만들 수 있다.
고객담당강사 릴레이션
강사번호(PK) | 고객아이디(PK) |
---|---|
P001 | apple |
P002 | banan |
P001 | carrot |
P003 | orange |
강좌담당 릴레이션
강사번호(PK) | 인터넷강좌 |
---|---|
P001 | 영어회화 |
P002 | 기초토익 |
P003 | 영어회화 |
P004 | 기초토익 |
제 4 정규형과 제 5 정규형
제 4 정규형과 제 5 정규형은 고급 정규형으로 분류된다.
제 4 정규형은 보이스/코드 정규형을 만족하면서 함수 종속이 아닌 다치 종속을 제거해야 만족할 수 있다. 제 5 정규형은 릴레이션이 제 4 정규형을 만족하면서 후보키를 통하지 않는 조인 종속을 제거해야 만족할 수 있다.
정규화 단계가 높을수록 최적화가 잘 된 데이터베이스 설계라고 할 수 있다. 정규화를 진행하면서 순수하게 서로 관련이 있는 데이터끼리 릴레이션을 구성하고, 데이터의 중복 저장을 피할 수 있기 때문이다. 하지만 실제로 데이터베이스를 설계할 때 모든 릴레이션을 제 5 정규형에 속하도록 만드는 것이 바람직하지는 않다. 오히려 제 5 정규형을 만족할 때까지 릴레이션을 분해하는 것이 비효율적이고 바람직하지 않은 경우가 많기 때문이다.
따라서 일반적인 경우 제 3 정규형 및 보이스/코드 정규형을 만족하도록 릴레이션을 분해하게 된다.
'일반 > 데이터베이스' 카테고리의 다른 글
권한 및 역할 (0) | 2022.06.27 |
---|---|
SQL을 이용한 데이터 정의 (0) | 2022.06.04 |