DB 정규화( normalization )란?

 

  • 테이블을 설계할 때 데이터 중복과 일관성 그리고 insertion, update, deletion anomaly를 최소화하기 위해 테이블을 분해하는 과정을 말합니다.




Normal forms란?

 

  • 정규화되기 위해 준수해야 하는 몇 가지 rule들이 있는데 이 각각의 rule을 normal form(NF)라고 부릅니다.




정규화를 알아보기 전의 간단한 용어 정리

 

  • prime attribute는 임의의 key에 속하는 attribute를 의미합니다.

 

  • non-prime attribute는 어떠한 key에도 속하지 않는 attribute를 의미합니다.




DB 정규화 과정

 


1NF -> 2NF -> 3NF -> BCNF -> 4NF -> 5NF -> 6NF

 

  • DB 정규화는 1NF부터 순차적으로 진행하며 앞 단계를 만족해야 다음 단계로 진행할 수 있습니다.




최소 정규화

 

  • 1NF ~ BCNF까지는 FD와 key만으로 정의되는 normal form입니다.

 

  • 보통 3NF까지 도달하면 정규화됐다고 말합니다. 실무에서도 3NF 혹은 BCNF까지만 진행하며 많이해도 4NF까지만 진행합니다.




정규화 예시

 

정규화할 employee_account 테이블

 

bank_name account_num account_id class ratio empl_id empl_name card_id




  • 임직원의 월급 계좌를 관리하는 테이블입니다.

 

  • 월급 계좌는 국민은행이나 우리은행 중 하나입니다.

 

  • 한 임직원이 하나 이상의 월급 계좌를 등록하고 각 계좌의 입금될 월급 비율(ratio)을 조정할 수 있습니다.

 

  • 계좌마다 등급(class)가 있습니다. ( 국민 : STAR -> PRESTIGE -> LOYAL, 우리 : BRONZE -> SILVER -> GOLD )

 

  • 한 계좌는 하나 이상의 현금 카드와 연동될 수 있다.

 

  • primary key는 account_id입니다.




1NF

 

bank_name account_num account_id class ratio empl_id empl_name card_id
Kookmin 010-1221-1732 a21 LOYAL 1 e2 Messi c201 c202




  • 1NF는 attribute의 value는 반드시 나눠질 수 없는 원자 값이어야 합니다.

 

  • card_id의 value를 보게된다면 나눠질 수 있는 값이기 때문에 1NF를 위반하고 있습니다.




2NF 과정

 

bank_name account_num account_id class ratio empl_id empl_name card_id
Kookmin 010-1221-1732 a21 LOYAL 1 e2 Messi c201
Kookmin 010-1221-1732 a21 LOYAL 1 e2 Messi c202




  • 위 테이블은 1NF를 만족합니다.

 

  • 모든 non-prime attribute는 모든 key에 fully functionally dependent해야 합니다. {account_id, card_id} key를 보았을 때 account_id만을 가지고 {class, ratio, empl_id, empl_name}의 non-prime attribute를 식별할 수 있습니다. 즉, {class, ratio, empl_id, empl_name}가 부분 함수적 종속된 상태입니다. 이와 같이 잘못된 테이블 설계로 인해서 card_id가 추가되었을 때 { class, raito, empl_id, empl_name }의 중복 데이터가 발생됩니다.




3NF

 

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

 

account_id card_id
a21 c201
a21 c202




  • 위 테이블들은 2NF를 만족합니다.

 

  • {account_id} -> {empl_id}, {empl_id} -> {empl_name}이기 때문에 {account_id} -> {empl_name} 관계도 성립됩니다.

 

  • {bank_name, account_num} -> {empl_id}, {empl_id} -> {empl_name}이기 때문에 {bank_name, account_num} -> {empl_name} 관계도 성립됩니다.

 

  • X -> Y, Y -> Z 관계로 인해 X -> Z가 성립되는 관계를 transitive FD라고 합니다.( Y와 Z는 어떤 key에 대해서도 부분 집합이 아니여야 합니다. )

 

  • 3NF는 모든 non-prime attribute는 어떤 key에 transitively dependent 하면 안됩니다. 즉, non-prime attribute들 간의 FD가 성립되면 안 됩니다. 즉, {bank_name, account_num}은 후보키 이기 때문에 {account_id} -> {class} -> {bank_name}는 이행 함수족 종속에 해당되지 않습니다.




BCNF

 

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

 

empl_id empl_name
e1 Sony
e2 Messi

 

account_id card_id
a21 c201
a21 c202




  • 위 테이블들은 3NF를 만족합니다.

 

  • class는 bank 마다 다 다른 계급을 가지기 때문에 {class} -> {bank_name} FD 관계를 가집니다.

 

  • BCNF는 모든 유효한 non-trivial FD의 X -> Y는 X가 반드시 후보 키 여야 합니다.




BCNF까지 만족한 테이블

 

account_num account_id class raito 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

 

bank_name class
Woori BRONZE
Woori SILVER
Woori LOYAL
Kookmin LOYAL

 

empl_id empl_name
e1 Sony
e2 Messi

 

account_id card_id
a21 c201
a21 c202




2NF 주의점

 

empl_id empl_name birth_date position salary company
1 ... ... ... ... ez.
2 ... ... ... ... ez.
3 ... ... ... ... ez.




  • company attribute의 값은 고정됨을 가정하겠습니다.

 

  • 위 테이블의 FD는 {empl_id} -> {empl_name, birth_date, position, salary, company}와 {} -> {company} 가 있습니다. 그리고 {}는 {empl_id}에 부분집합이며 company는 {empl_id}에 부분 함수적 종속관계이기 때문에 2NF를 만족하지 못합니다.

 

  • 위와 같은 예외 상황이 발생될 수 있기 때문에 2NF는 key가 composite key( 두 개 이상으로 이루어진 key )가 없다면 자동적으로 2NF를 만족한다? 라고 할 수는 없습니다.




denormalization 이란?

 

empl_id empl_name birth_date position salary
1 ... ... ... ...
2 ... ... ... ...
3 ... ... ... ...

 

company
ez.




  • 위 테이블은 2NF를 만족시키기 위해서 {empl_id} primary key의 부분 함수족 종속인 company attribute를 분리하여 {}->{company}를 제거하고 company를 위한 새로운 테이블을 구성하였습니다. 위와 같은 정규화는 어떻게 보면 과할 수 있습니다. 그리고 경우에 따라서 테이블을 너무 과도하게 분리하게 될 경우 너무 많은 join으로 인한 성능 저하 그리고 관리적인 측면에서 어려움이 있기 때문에 적정 수준을 잘 조절하며 정규화를 해야합니다.




+ Recent posts