이상현상이란, 테이블 내의 데이터들이 불필요하게 중복되어 테이블을 조작할 때 발생되는 데이터 불일치 현상이다.
테이블을 잘못 설계하여 삽입, 삭제, 갱신할 때 오류가 발생하게 되는 것이다.
이상현상에는 크게 3가지 이상현상이 있으며, 정규화를 통해서 이상현상들을 해결할 수 있다.
한 릴레이션에 여러 엔티티의 애트리뷰트들을 혼합하게 되면 정보가 중복 저장되며, 저장 공간을 낭비하게 된다. 또 중복된 정보로 인해 갱신 이상이 발생하게 된다. 동일한 정보를 한 릴레이션에는 변경하고, 나머지 릴레이션에서는 변경하지 않은 경우 어느 것이 정확한지 알 수 없게 되는 것이다. 이러한 문제를 해결하기 위해 정규화 과정을 거치는 것이다.
함수 종속성(Functional Dependency)은 어떤 테이블의 속성 A와 B에 대하여, A값에 의해 B값이 유일하게 정해지는 관계를 말하며, "B는 A에 함수 종속이다"라고 한다. A→B의 기호로 나타낸다.
이때, A를 결정자(Determinant)라고 하고, B를 종속자(Dependant)라고 한다.
함수 종속성은 크게 완전 함수 종속과 부분 함수 종속, 이행적 함수 종속으로 나뉜다.
완전 함수 종속 : 기본키를 구성하는 모든 속성에 종속되는 경우
부분 함수 종속 : 기본키를 구성하는 속성의 일부에 종속되거나, 기본키가 아닌 다른 속성에 종속되는 경우
이행적 함수 종속 : A, B, C 세 속성이 있고 A→B, B→C 종속 관계가 있을 때, A→C가 성립하는 경우
위와 같은 테이블이 있다고 하자. 여러 학생들이 있고 각 학생별로 여러 과목을 수강한다고 할 때, 위 테이블의 기본키는 (학번, 과목번호)가 될 것이다.
그렇다면, 이름과 학년은 학번만 알아도 유일하게 결정된다. 반면에 성적은 학번과 과목 번호를 모두 알아야 유일하게 결정된다. 따라서 그림으로 표현하면 다음과 같다.
그러므로, 학년과 이름은 (학번, 과목번호)에 대해 부분 함수 종속이고, 성적은 완전 함수 종속이다.
이렇게 엔티티를 구성하는 속성간의 함수 종속성을 판단하여 좋은 릴레이션인지 알 수 있다.
제2 정규화란 제1 정규화를 진행한 테이블에 대해 완전 함수 종속을 만족하도록 테이블을 분해하는 것이다.
여기서 완전 함수 종속이라는 것은 기본키의 부분집합이 결정자가 되어선 안된다는 것을 의미한다.
예를 들어 아래와 같은 수강 강좌 테이블을 살펴보자.
제3 정규화란 제2 정규화를 진행한 테이블에 대해 이행적 종속을 없애도록 테이블을 분해하는 것이다.
여기서 이행적 종속이라는 것은 A -> B, B -> C가 성립할 때 A -> C가 성립되는 것을 의미한다.
예를 들어 아래와 같은 계절 학기 테이블을 살펴보자.
기존의 테이블에서 학생 번호는 강좌 이름을 결정하고 있고, 강좌 이름은 수강료를 결정하고 있다. 그렇기 때문에 이를 (학생 번호, 강좌 이름) 테이블과 (강좌 이름, 수강료) 테이블로 분해해야 한다.
이행적 종속을 제거하는 이유는 비교적 간단하다. 예를 들어 501번 학생이 수강하는 강좌가 스포츠경영학으로 변경되었다고 하자. 이행적 종속이 존재한다면 501번의 학생은 스포츠경영학이라는 수업을 20000원이라는 수강료로 듣게 된다. 물론 강좌 이름에 맞게 수강료를 다시 변경할 수 있지만, 이러한 번거로움을 해결하기 위해 제3 정규화를 하는 것이다.
즉, 학생 번호를 통해 강좌 이름을 참조하고, 강좌 이름으로 수강료를 참조하도록 테이블을 분해해야 하며 그 결과는 다음의 그림과 같다.
각종 이상 현상들을 해결할 수 있다.
새로운 속성의 추가로 인해 DB 구조를 확장하는 경우, 구조의 변경을 최소화할 수 있다. 따라서 DB와 연동된 응용프로그램에 최소한의 영향만을 미쳐 응용프로그램의 생명을 연장시킨다.
정규화된 릴레이션 간의 관계가 현실 세계에서의 개념들간의 관계를 잘 보여준다.
릴레이션의 분해로 인해 릴레이션간의 연산이 많아져 응답 시간이 오히려 느려질 수도 있는 단점이 있다.
이러한 경우 반정규화(De-normalization)을 통해서 성능을 향상시킬 수 있다.
반정규화(De-normalization)은 시스템의 성능 향상을 위해 정규화된 데이터 모델을 통합하는 작업으로, 의도적으로 정규화 원칙을 위배하는 행위이다. 따라서 정규화와 반정규화는 Trade-off 관계에 있다.
조회를 하는 SQL 문장에서 조인이 많이 발생하여 이로 인한 성능저하가 나타나는 경우에 반정규화를 적용하는 전략이 필요하다.
반정규화의 종류로는 테이블 통합/분할/추가, 중복 속성 추가 등이 있다.
반정규화를 수행하면 테이블이 단순해지고 관리 효율성이 증가하지만, 데이터의 일관성이나 무결성이 보장되지 않을 수 있다. 의도적으로 중복을 생성하여 검색 기능은 향상되지만, 갱신, 삭제 등의 성능은 낮아진다.
따라서 데이터의 중복 방지, 무결성 vs 데이터베이스의 성능, 단순화 사이의 우선순위를 잘 조절하여 정규화/반정규화를 수행해야 한다.
수행 속도가 많이 느린 경우
테이블의 조인(JOIN)연산을 지나치게 사용하여 데이터를 조회하는 것이 기술적으로 어려운 경우
테이블에 많은 데이터가 있고, 다량의 범위 혹은 특정 범위를 자주 처리해야 하는 경우