잘못된 DB 테이블 설계 시 발생하는 문제
이상현상(Anomaly)
- 삽입 이상(Insertion Anomalies): 튜플 삽입 시 특정 속성에 해당하는 값이 없어 NULL을 입력해야 하는 현상
- 저장 공간 낭비
- 실수로 인한 데이터 불일치 가능성 존재
- null 값을 많이 쓰게 됨
- 삭제 이상(Deletion Anomalies): 튜플 삭제 시 같이 저장된 다른 정보까지 연쇄적으로 삭제되는 현상
- 수정 이상(Update Anomalies): 튜플 수정 시 중복된 데이터의 일부만 수정되어 일어나는 데이터 불일치 현상
Spurious(가짜) Tuples
- 잘못된 종속성을 갖게 테이블을 natrual join 시 가짜 정보가 발생
NULL 값이 많아짐으로 인한 문제점들
- null 값이 있는 column으로 join 하는 경우 상황에 따라 예상과 다른 결과 발생
- null 값이 있는 column에 aggregate function을 사용했을 때 주의 필요
- count(*)를 쓰면 null도 포함해서 카운트함.
- 불필요한 storage 낭비
Functional Dependency(FD, 함수 종속성)
함수 종속성이란?
- 어떤 속성 X의 값을 알면 다른 속성 Y의 값이 유일하게 정해지는 관계를 종속성이라 함
- X가 Y를 함수적으로 결정한다(functionally determine)
- Y가 X에 함수적으로 의존한다(funcdtionally dependent)
X -> Y
로 표기하며 X를 Y의 결정자라고 한다.
함수 종속성 파악하기
테이블의 스키마를 보고 의미적으로 파악해야 한다
즉, 테이블의 특정 순간(state)만 보고 FD를 파악해서는 안된다!
ex) 동명이인이 있을 수 있는데, 당시의 state만 보고 이름이 다른 속성을 결정한다고 생각하면 안된다
함수 종속성의 종류
Trivial FD
: X->Y가 유효할 때, Y가 X의 부분 집합인 경우- e.g.) { a, b, c } -> { c }는 trivial FD이다.
- e.g.) { a, b, c } -> { a, c }는 trivial FD이다.
- e.g.) { a, b, c } -> { a, b, c }는 trivial FD이다.
Non-Trivial FD
: X → Y가 유효할 때, Y가 X의 부분 집합이 아닌경우- e.g.) { a, b, c } → { b, c, d }는 non-tirivial FD이다.
- e.g.) { a, b, c } → { d, e }는 non-tirivial FD이다. => 이 두 집합은 공통된 attributes가 하나도 없다.
- 두 집합의 공통된 attributes가 하나도 없을 경우, completely
non-triival FD
Partial FD
(부분 함수 종속): X → Y가 유효할 때, X 집합의 그 어떤 proper subset이 Y를 결정할 수 있는 경우- proper subset: 집합 X의 proper subset은 X의 부분집합이지만, X와 동일하지는 않은 집합
- e.g.) X = { a, b, c }일 때, { a, b, c }를 제외한 모든 부분 집합은 proper subset이다.
- e.g.) { empl_id, empl_name } → { birth_date }가 유효하다면, { empl_id } 만으로도 { birth_date } 를 결정할 수 있으므로 이는 partial FD이다.
- proper subset: 집합 X의 proper subset은 X의 부분집합이지만, X와 동일하지는 않은 집합
Full FD
(완전 함수 종속): X → Y가 유효할 때, X 집합의 그 어떤 proper subset이 Y를 결정할 수 없는 경우 (partial FD의 반대)- e.g.) { stu_id, class_id } → { grade } 가 유효하다면, proper subset인 { stu_id }, { class_id }, {}은 { grade }를 결정할 수 없으므로 이 FD는 Full FD이다.
Transitive FD
(이행적 함수 종속): X -> Y가 유효하고, Y -> Z가 유효할 때, X -> Z를 만족하는 경우- e.g.) { a } -> { b, c }이고, { b } -> { c }일 경우, { a } -> { c }도 유효하므로 이는 Transitive FD이다.
DB 정규화
: 데이터 중복과 이상 현상을 최소화하기 위해 일련의 normal forms(NF)에 따라 relational DB를 구성하는 과정
Normal Forms(NF)
- 정규화되기 위해 준수해야 하는 몇 가지 rule들이 있는데 이 각각의 rule을 normal form(NF)이라고 부른다.
- 1NF부터 6NF 까지 차례대로 있으며, 처음부터 순차적으로 진행하며, normal form을 만족하지 못하면 만족하도록 테이블 구조를 조정한다.
- 앞 단계를 만족해야 다음 단계로 진행할 수 있다.
1NF
~BCNF
- FD와 key 만으로 정의되는 normal forms
- 3NF까지 도달하면 정규화 됐다고 말하기도 함
- 보통 실무에서는 3NF 혹은 BCNF까지 진행(많이 해도 4NF 정도까지만 진행)
1NF(제 1정규형)
- attribute의 value는 반드시 나눠질 수 없는 단일한 값이어야 한다.
- 즉, 릴레이션의 모든 속성이 원자값을 가져야 한다.

2NF(제 2정규형)
- 제 1정규형을 만족하고, 기본키가 아닌 속성이 기본 키에 완전 함수 종속(Full FD)이어야 한다.

3NF(제 3정규형)
- 제 2정규형을 만족하고, 기본키가 아닌 속성이 기본키에 비행적 종속(Non-Transitive FD)이어야 한다.
- 기본키와 기본키가 아닌 속성 사이에 FD가 있으면 안된다

BCNF
- 함수 종속성 X -> Y가 성립할 때, 모든 결정자 X가 후보키이어야 한다.
- 모든 유효한 비이행적 종속은 X가 super key이어야 한다.
- 기본키는 (학생번호, 특강이름)이고, 교수는 (학생번호, 특강이름)에 Full FD를 만족한다. 또한, 교수 역시 특강 이름에 대해 결정자의 역할을 하고 있다. 다음으로 모든 결정자 X가 후보키인지를 확인해야 한다. (학생번호, 특강이름)은 기본키이므로 당연히 결정자이며 후보키이다. 하지만, 교순는 결정자이며 후보키가 아니므로 아래의 예시는 BCNF 정규형이 아니다.

2NF 참고 사항
2NF는 key가 composite key(복합키)가 아니라면 자동적으로 만족된다?
보통은 맞는 설명이다. composite key가 있어야만 기본키가 아닌 속성이 그 키에 대하여 fully or partially dependent 한 지를 파악할 수 있을 것이다. 즉, omposite key가 없다면 partially dependent한 경우 자체가 없으므로 composite key가 없다면 자동으로 2NF를 만족하게 될 것이다.
하지만, 예외가 하나 있다. {} -> Y의 경우이다! 즉, 항상 일정한 값을 갖는 기본키가 아닌 속성의 경우

⇒ company는 {empl_id}에 partially dependent하고 있다.

이런 모습이 되어야 한다.
하지만, 나는 그냥 원래대로 쓰겠다. 정규화하지 않겠다 하는 것이 바로 denormalization(반정규화)이다.
Denormalization(반정규화, 역정규화)
테이블을 너무 많이 쪼개면, 여러 테이블 조인하면서 성능 이슈 및 관리가 어려워지는 단점이 있다.
⇒ BCNF → 3NF와 같이 원래 쪼갰던 테이블을 다시 합치는 과정을 하기도 한다.
⇒ DB를 설계할 때 과도한 조인과 중복 데이터 최소화 사이에서 적정 수준을 잘 선택할 필요가 있다.
'Database' 카테고리의 다른 글
[Database] Transaction Isolation Level (0) | 2024.10.06 |
---|---|
[Database] Transaction, Concurrency Control (1) | 2024.10.06 |
[Database] SQL Trigger (0) | 2024.10.05 |
[Database] Stored Function & Stored Procedure (2) | 2024.10.05 |
[Database] SQL 고급 (1) | 2024.10.05 |