Database

데이터베이스 정규화 - (2) 제 3 정규화, BCNF, 역 정규화

자몽포도 2023. 5. 1. 02:40

본 포스팅은 쉬운코드님의 정규화 영상 2부 을 기반으로 정리하였습니다. functional dependency(FD)를 사용해서 DB를 정규화하는 방법을 배웁니다.

 

목차

1. 제 3 정규화

2. BCNF

3. 역정규화

 

이전 시간에 배운 내용을 잠시만 정리하겠습니다.

제1 정규화 : attirbute의 value는 반드시 나눠질 수 없는 단일한 값이여야 한다.

제 2 정규화 : 모든 non-prime attribute는 모든 key에 fully functionally dependent 해야 한다.


제 3 정규화 : 모든 non-prime attribute는 어떤 key에도 transitively dependent 하면 안된다.


이 말을 조금 더 쉽게 말하면 non-prime attribute 사이에는 FD가 존재하면 안된다라는 말입니다.

bank_name act_name account_id class ratio empl_id empl_name
woori 010-9231-1121 a11 BRONZE 0.1 e1 Sony
woori 102-992-180125 a12 SILVER 0.2 e1 Sony
Kookmin 010-9231-1121 a13 LOYAL 0.7 e1 Sony
Kookmin 010-1221-1732 a21 LOYAL 1 e2 Messi

 

위 테이블은 제 2 정규화 작업까지 진행되었습니다. Functional Dependency를 살펴봅시다.

 

empl_id 는 empl_name 을 결정할 수 있습니다. empl ➔ empl_name

account_id는 empl_id 를 결정할 수 있습니다. account_id ➔ empl_id

 

Transitive Functional Dependent

위 FD를 정리하면 이와 같은 결로이 나옵니다. account_id ➔ empl_id ➔ empl_name

X ➔ Y & Y ➔ Z 여서 X ➔ Z 인 FD를 transitive FD라고 부릅니다.

 

Transitive Functional Dependent 예외

transitive FD 는 예외를 가집니다. X ➔ Z 일 때, Y, Z가 어떤 key에도 속하면 안됩니다.

 

예를 들어 살펴보겠습니다. account_id ➔ class & class ➔ bank_name 입니다. 이에 따라 account_id ➔ bank_name 도 FD라고 생각 할 수 있습니다. 하지만 이 경우에는 bank_name 이 key에 속하기 때문에 예외 사항에 해당하여 Transitive FD가 아니게 됩니다.

 

 

다시 제 3 정규화로 돌아오겠습니다. 현재 존재하는 FD를 제거해야 합니다. 이를 위해 테이블을 분리하겠습니다.

 

EMPLOYEE_ACCOUNT

bank_name act_name account_id class ratio empl_id
woori 010-9231-1121 a11 BRONZE 0.1 e1
woori 102-992-180125 a12 SILVER 0.2 e1
Kookmin 010-9231-1121 a13 LOYAL 0.7 e1
Kookmin 010-1221-1732 a21 LOYAL 1 e2

 

 

EMPLOYEE

empl_id empl_name
e1 Sony
e2 Messi

 

 

이로서 제3 정규화가 되었고 여기까지 진행되면 정규화됐다라고 말할 수 있습니다.

 

 

 

BCNF : 모든 유효한 non-trivial FD X ➔ Y 는 X가 super key 여야 한다.


여기서 super key란 테이블에서 한 튜플을 유니크하게 식별할 수 있는 attribute를 말합니다. 

non trivial FD란, Y가 X의 부분집합이 아닌 FD를 말한다.

bank_name act_name account_id class ratio empl_id
woori 010-9231-1121 a11 BRONZE 0.1 e1
woori 102-992-180125 a12 SILVER 0.2 e1
Kookmin 010-9231-1121 a13 LOYAL 0.7 e1
Kookmin 010-1221-1732 a21 LOYAL 1 e2

 

사실 class / bank_name 간 중복데이터가 발생할 수 있다.1편에서 정의했던 스펙을 살펴보면 이러한 정보를 볼 수 있습니다.

 

국민은행 계좌 등급(class) : STAR ➔ PRESTIGE ➔ LOYAL

우리은행 계좌 등급(class) : BRONZE ➔ SILVER ➔ GOLD

 

두 은행의 계좌 등급이 겹치지 않기 때문에 class만 보고 bank_name 을 알 수 있습니다. 즉 class ➔ bank_name 입니다.

해당 FD는 non trivial FD입니다. 그리고 class는 super key가 아닙니다. BCNF 제약에 벗어나기 때문에 제거해야 하는 FD입니다. 이를 위해 테이블을 다시 분리합니다.

 

EMPLOYEE_ACCOUNT

act_name account_id class ratio empl_id
010-9231-1121 a11 BRONZE 0.1 e1
102-992-180125 a12 SILVER 0.2 e1
010-9231-1121 a13 LOYAL 0.7 e1
010-1221-1732 a21 LOYAL 1 e2

 

ACCOUNT_CLASS

bank_name class
woori GOLD
woori BRONZE
woori SILVER
Kookmin LOYAL
Kookmin PRESTIGE 
Kookmin STAR 

 

 

역정규화 


역 정규화란 정규화 되어있던 테이블을 다시 합쳐 이전 정규화 단계로 돌아가는 것을 말합니다. 그렇다면 이러한 작업이 왜 필요한 것일까요? 제3 정규화를 진행하면서 테이블은 1개에서 4개로 늘어나게 되었습니다. 한 번 살펴보시죠.

제1 정규화 이전 테이블

_name act_name act_id class ratio empl_id empl_name card_id
woori 010-9231-1121 a11 BRONZE 0.1 e1 Sony c101
woori 102-992-180125 a12 SILVER 0.2 e1 Sony c102
Kookmin 010-9231-1121 a13 LOYAL 0.7 e1 Sony c103
Kookmin 010-1221-1732 a21 LOYAL 1 e2 Messi c201,c202

 

 

제3 정규화가 끝난 테이블

EMPLOYEE_ACCOUNT

bank_name act_name act_id class ratio empl_id
woori 010-9231-1121 a11 BRONZE 0.1 e1
woori 102-992-180125 a12 SILVER 0.2 e1
Kookmin 010-9231-1121 a13 LOYAL 0.7 e1
Kookmin 010-1221-1732 a21 LOYAL 1 e2

 

ACCOUNT

act_id card_id
a11 c101
a12 c102
a13 c103
a21 c201
a21 c202

 

EMPLOYEE

empl_id empl_name
e1 Sony
e2 Messi

 

ACCOUNT_CLASS

bank_name class
woori GOLD
woori BRONZE
woori SILVER
Kookmin LOYAL
Kookmin PRESTIGE 
Kookmin STAR 

 

제3 정규화를 거치면서 테이블이 1개에서 4개로 늘어나게 되었다. 이로 인해서 많은 부분에서 데이터 중복을 제거하고 insertion, update, deletion anomaly 문제를 방지할 수 있게 되었습니다. 하지만 테이블이 늘어나게 되면서 join 사용이 늘어나 성능에 악영향을 미칠 수 있습니다. 또한 힘들어지게 될 것입니다. 정규화로 인한 단점을 해결하기 위해 역 정규화를 진행하기도 한다고 합니다.

 

DB 설계 시 과도한 조인과 중복 데이터 최소화 사이에서 적정 수준을 잘 선택할 필요가 있다고 합니다.