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으로 인한 성능 저하 그리고 관리적인 측면에서 어려움이 있기 때문에 적정 수준을 잘 조절하며 정규화를 해야합니다.
'데이터 베이스 > RDBMS' 카테고리의 다른 글
Clustered Index와 Non-Clustered Index (0) | 2023.02.11 |
---|---|
DB index란? 그리고 index의 기본 동작 방식과 사용법 (0) | 2023.02.10 |
Functional Dependency( FD )란? (0) | 2023.02.08 |
잘못된 DB 테이블 설계로 인한 이상현상 (0) | 2023.02.08 |
transaction의 이상 현상과 isolation level (0) | 2023.02.06 |