🎆 이상 현상이란?
DB를 잘못 설계하면 불필요한 데이터 중복이 발생해 릴레이션에 대한 데이터의 삽입, 수정, 삭제 연산을 수행할 때 부작용이 발생할 수 있는데 이것이 이상현상이다.
1. 삽입 이상 (inserion anomaly)
릴레이션에 새 데이터를 삽입할 때 원치 않는 불필요한 데이터도 삽입하는 문제
- 아이디가 melon이고 이름이 홍길동, 등급이 gold이다. 이벤트 참여 릴레이션에 고객 데이터를 삽입해야한다.
- 이벤트참여 릴레이션의 PK가 고객아이디와 이벤트번호 속성이라면, 이벤트번호는 NULL값을 가질 수 없기에 임시 이벤트 번호를 삽입해야한다.
2. 갱신 이상 (update anomaly)
릴레이션의 중복된 튜플 중 일부만 수정해 데이터가 불일치하게 되는 모순이 발생하는 문제
- 아이디가 apple인 고객의 등급이 gold에서 vip로 변경되면 이벤트 참여 릴레이션에서 apple 고객에 대한 등급 속성값이 모두 수정되어야 한다.
- 이 때 모두 수정되지 않으면 apple고객이 여러 등급을 가지는 모순이 생겨 갱신이상이 발생한다.
3. 삭제 이상 (deletion anomaly)
릴레이션에서 튜플을 삭제하면 꼭 필요한 데이터까지 삭제되어 데이터가 손실되는 연쇄 삭제 현상
- 이벤트참여 릴레이션에서 아이디가 orange인 고객이 E4번 이벤트 참여를 취소한다고 하자.
- E4 정보만 가지고있는 것이 아니라 고객아이디, 고객이름, 등급에 대한 정보도 가지고 있다면 E4가 있는 튜플이 삭제되면 이벤트 참여와 관련이 없어도 해당 고객에 대한 고객아이디, 고개이름, 등급까지 원치않게 삭제 된다.
4. 정규화의 필요성
이벤트참여 릴레이션에 여러 이상 현상이 발생하는 이유는?
- 관련이 없는 데이터, 속성들을 하나의 릴레이션에 모두 모아두고 있기 때문이다.
- 이상 현상이 발생하지않으려면 관련 있는 속성으로만 릴레이션을 구성해야하는데 이 때 정규화 과정이 필요하다.
- 정규화는 이상 현상이 발생하지 않도록 릴레이션을 분해한다.
- 정규화 수행 전 먼저 릴레이션을 구성하는 속성들 간의 관련성을 판단해야한다
- 고려하는 속성들 간의 관련성은 함수적 종속성(FD; Funcional Dependency)라고 하며 일반적으로 릴레이션에 함수적 종속성이 하나 존재하도록 정규화한다.
-> 함수적 종속성의 의미와 함수적 종속성 판단 방법에 대해 알아보도록 하자.
🎆 함수 종속성
하나의 릴레이션을 구성하는 속성들의 부분집합을 X, Y라 하자. 어느 시점에서든 릴레이션 내의 모든 튜플에서 X값에 대한 Y값이 항상 하나이면, "X가 Y를 함수적으로 결정한다." , "Y는 X에 함수적으로 종속되어 있다."
X->Y로 표현하며 X를 결정자, Y를 종속자라고 한다.
- 예를 들어, 고객 릴레이션에서 고객아이디 속성값에 대응되는 고객이름과 등급속성은 단 하나이다. 그러면 고객아이디가 고객이름과 등급을 결정한다.
- 고객아이디 -> (고객이름, 등급), X->Y, 결정자 -> 종속자 이다.
- 위는 다음과 같은 함수 종속 다이어그램으로 표현할 수 있다.
1. 완전 함수적 종속
- 릴레이션에서 속성 집합 Y가 속성 집합 X에 함수적으로 종속되어있지만, 속성 집합 X에 전체 종속이지 일부분에 종속된 것이 아니다.
2. 부분 함수적 종속
- 속성집합 Y가 속성 집합 X의 전체가 아닌 일부분에도 함수적으로 종속되어 있다.
고객아이디 -> 고객이름
, (고객아이디, 이벤트번호) -> 당첨여부
, (고객아이디, 이벤트번호) -> 고객이름
이라면 고객이름은 부분 함수 종속이며 당첨여부는 완전 함수 종속이다.
🎆 정규화 (Normalization)
위에서 설명한 함수 종속성을 이용해 릴레이션을 연관성 있는 속성들로만 구성되도록 분해하여 이상현상이 발생하지 않게 하는 것이 정규화이다.
- 릴레이션이 정규화된 정도는 정규형(NF; Normal Form)으로 표현한다.
- 제1정규형, 제2정규형, 제3정규형, BCNF(보이스/코드)정규형 등이 있다.
- 각 정규형마다 만족시켜야하는 제약조건이 존재한다.
- 정규형의 차수가 높아질수록 요구되는 제약조건이 많고 데이터 중복이 줄어든다.
- 무조건 높은 정규형에 속해야하는 것이 아니라, 릴레이션의 특성을 고려해 적합한 정규형을 선택해야한다.
- 정규화 과정에서 릴레이션을 분해하는 것은 무손실 분해여야한다.
릴레이션에 속한 모든 속성의 도메인이 원자값으로만 구성된다. (도메인이 원자값)
- 릴레이션에 속한 모든 속성이 더는 분해되지 않는 원자값이어야한다.
- 이벤트 참여 릴레이션에서 한 명이 여러 이벤트에 참여하여 이벤트번호가 E1, E5이렇게 가진다면 다중값이므로 제1정규형에 속하지 못한다.
- 튜플마다 이벤트 번호를 한개씩 가지도록 분해해야한다.
릴레이션이 제1정규형이며, 기본키가 아닌 모든 속성이 기본키에 완전 함수 종속이 되어야한다. (부분 함수 종속 제거)
- 모든 속성이 기본키에 완전 함수 종속되도록 릴레이션을 분해한다.
릴레이션이 제2정규형이며 기본키가 아닌 모든 속성이 기본키에 이행적 함수종속이 되지 않아야한다. (이행적 함수 종속 제거)
- 이행적 함수 종속(transtive FD): 릴레이션에서 3개의 속성집합 X, Y, Z가 있다면 X->Y, Y->Z이면 X->Z가 성립한다. 이때 속성 집합 Z는 X에 이행적으로 함수 종속이다.
릴레이션이 제3정규형이며 함수종속관계에서 모든 결정자가 후보키이다. (결정자가 후보키)
- 하나의 릴레이션에는 여러 개의 후보키가 존재 가능하다. 이 때는 제3정규형에서도 이상 현상이 발생할 수 있다.
✨ 제4정규형, 제5정규형
제4정규형은 BCNF정규형이며 다치 종속을 제거하고 제5정규형은 제4정규형이며 조인 종속을 제거해야한다.
- 실제로 DB를 설계할때 모든 릴레이션이 제5정규형에 속하면 비효율적이고 바람직해지지않아질 수 있다.
- 일반적으로 제3정규형이나 BCNF정규형에 속하제 릴레이션을 분해한다.
🎆 반정규화 (De-Normalization)
릴레이션에서 고의적으로 중복 저장하여 조회 성능을 향상시키는 기법. 테이블 병합, 테이블 분할, 테이블 추가가 있다.
- 데이터무결성이 깨질 수 있다.
- 조회(Read)는 빨라지고 입력(Create), 수정(Update), 삭제(Delete)는 느려진다.
- 다량의 범위를 자주 처리해야할 때 사용한다.
테이블 반정규화
1. 테이블 병합
- 여러 테이블 간의 조인을 피하고자 할 때 사용한다.
- 1:1 관계 테이블 병합, 1:M 관계 테이블 병합, 슈퍼/서브 테이블 병합이 있다.
2. 테이블 분할
- 테이블 수직 분할: 속성 분할
- 테이블 수평 분할: 인스턴스 분할, 파티셔닝
3. 테이블 추가
- 중복테이블 추가
- 통계테이블 추가
- 이력테이블 추가
- 부분테이블 추가
컬럼 반정규화
- 중복컬럼추가
- 파생컬럼추가: 미리 계산해 컬럼 보관
- 이력테이블 컬럼추가: 기능성컬럼(최근값, 시작일자, 종료일자 등)
관계 반정규화
- 중복관계추가: 성능저하 예방을 위한 추가적인 관계 (중복 FK 등)