정규화
개념
정규화 필요성
-
관련이 없는 속성들을 한 테이블에 모아두었기 때문에 이상 현상이 발생한다
-
이상 현상을 제거하면서 DB를 설계해나가는 과정이 정규화
- 이상 현상이 발생하지 않도록 릴레이션을 분해하는 과정
-
정규화를 통해 관련 있는 속성들로만 테이블을 구성한다
정규형
- 각 정규형마다 만족시켜야 하는 조건이 존재한다
- 정규형의 차수 ↑
- 요구되는 제약조건 ↑
- 일반적으로 데이터 중복 ↓, 이상 현상 ↓
정규형의 종류
- 기본 정규형
- 제1정규형
- 제2정규형
- 제3정규형
- 보이스/코드 정규형
- 고급 정규형
릴레이션에 속한 모든 속성의 도메인이 원자 값으로만 구성
- 모든 속성이 원자 값만 가져야 함
- 다중 값 속성 x
예시 (비정규형)
- event (customer_id, event_id, winning_status, membership_level, discount)
- (apple, (e1,e2), (Y, N), gold, 10)
- (orange, e1, N, gold, 10)
- 한 고객에 event_id와 winning_status가 2개이므로 1NF x
1NF로 분해
- (apple, e1, Y, gold, 10)
- (apple, e2, N, gold, 10)
- 제1정규형을 만족하지만 불필요한 데이터 중복 > 이상 현상 발생 가능
함수 종속성 살펴보기
- customer_id → memebership_level
- customer_id → discount
- membership_level → discount
- (customer_id, event_id) → winning_status
이상 현상 발생
1. 삽입 이상
-
기본키는 {customer_id, event_id}
-
고객 데이터를 추가하려면 무조건 이벤트에 참여해야 한다
-
이벤트를 참여하지 않는 데이터는 기본키의 일부인 event_id가 NULL
→ 개체 무결성 제약조건 위반
2. 갱신 이상
- apple 고객의 튜플이 2개이므로 membership_level과 discount가 중복되어 있음
- (apple, e1, Y, gold, 10)
- (apple, e2, N, gold, 10)
- apple 고객의 멤버십 등급을 vip로 변경할 때, 일부 튜플만 변경된다면
→ 데이터 일관성 위반
3. 삭제 이상
-
(orange, e1, N, gold, 10)
-
orange 고객이 이벤트 참여를 취소한다면 고객 정보도 함께 삭제해야 함
→ 필요한 데이터 유지 불가
이상 현상 발생 이유
- 기본키인 {customer_id, event_id}가 완전 함수 종속x
- membership_level과 winning_status가 중복되어 저장
- customer_id와 event_id, winning_status가 관련x
- 릴레이션을 분해하여 제2정규형에 속하도록 변경해볼 것
릴레이션에 제1규형에 속하고, 기본키가 아닌 모든 속성이 기본키에 완전 함수 종속
예시 (1NF)
- event (customer_id, event_id, winning_status, membership_level, discount)
- (apple, e1, Y, gold, 10)
- (apple, e2, N, gold, 10)
- (orange, e1, N, vip, 15)
- 기본키 (customer_id, event_id)에 membership_level, discount가 완전 함수 종속x
2NF로 변경
- event 릴레이션을 customer, event 릴레이션으로 분해
- customer (customer_id, membership_level, discount)
- membership_level, discount가 완전 종속
- 고객 한 명에 멤버십 등급과 할인율이 각각 하나
- event (customer_id, event_id, winning_status)
- winning_status가 완전 종속
- 한 고객이 참여한 하나의 이벤트는 당첨여부가 하나
이상 현상 발생
- event 릴레이션은 함수 종속성 하나
- customer 릴레이션은 함수 종속성 여러 개 (완전 함수 종속성이지만)
→ 이상 현상 발생 가능
1. 삽입 이상
- 지금까지 membership_level에는 gold와 vip 등급밖에 없었다
- silver라는 등급을 추가하려면 고객 아이디가 NULL로 들어가야 함
2. 갱신 이상
- vip의 할인율을 15에서 20으로 변경하려고 한다
- customer 릴레이션에서 gold인 튜플은 2개인데, 만약 하나의 튜플에 discount가 갱신되지 않는다면 한 멤버십 등급에 여러 할인율이 생긴다
→ 데이터 불일치
3. 삭제 이상
- orange 고객이 탈퇴하면 vip라는 등급과 vip의 할인율 정보가 함께 삭제된다
→ 데이터 손실
이상 현상 발생 이유
- 한 릴레이션에 함수 종속 관계 여러 개
- 릴레이션을 분해하여 이행적 함수 종속 제거
- 3NF로 변경해 보기
릴레이션이 제2정규형에 속하고 기본키가 아닌 모든 속성이 기본키에 이행적 함수 종속 x
-
2NF를 만족해도 한 릴레이션에 여러 개의 함수 종속 관계가 존재해서 이행적 함수 종속 관계가 유도되면 이상 현상 발생 가능
-
모든 속성이 기본키에 이행적 함수 종속이 되지 않도록 릴레이션 분해
-
함수적 종속성 보장, 하지만 데이터 중복 가능
예시 (2NF)
- event (customer_id, event_id, winning_status, membership_level, discount)
- (apple, e1, Y)
- (apple, e2, N)
- (orange, e1, N)
- (carrot, e3, Y)
- customer (customer_id, membership_level, discount)
- (apple, gold, 10)
- (orange, vip, 15)
- (carrot, gold, 10)
3NF로 변경
- customer 릴레이션에 이행적 함수 종속 관계 존재
- customer_id → membership_level
- membership_level → discount
- customer_id(PK) → discount
- 2개의 릴레이션으로 분해
- X→Y, Y→Z, X→Z면 (X, Y), (Y, Z) 릴레이션으로 분해
- customer (customer_id, membership_level, discount)
- customer(customer_id, membership_level)
- membership(membership_level, dicount)
릴레이션의 함수 종속 관계에서 모든 결정자가 후보키
-
한 릴레이션에 여러 개의 후보키가 존재하는 경우, 3NF를 만족하더라도 이상현상 발생 가능
-
제3규형에 더 강력한 제약조건 추가
- 강한 제3정규형이라고도 함
-
BCNF와 dependency preserving을 동시에 만족하는 것이 항상 가능x
- 그래서 BCNF보다 약한 조건인 3NF (weaker BCNF)가 등장
예시 (BCNF x)
-
inst_dep (id, name, salary, dept_name, building, budget)
-
dept_name → building, budget이지만
-
dept_name은 후보키가 아님
BCNF 분해
- 스키마 R의 속성 집합 X, Y의 함수적 종속성인 X→Y가 BCNF을 위반한다면 다음과 같이 분해한다
- inst_dep을 instructor, department로 분해
- department (dept_name, building, budget)
- instructor (id, name, salary, dept_name)
- R: inst_dept, X: dept_name, Y: (building, budget)
출처: 데이터베이스 개론, Database System Concepts