[Database] 정규화(Normalization)/비정규화(Denormalization)

오늘은 효율적인 데이터베이스 설계를 위한 정규화(Normalization) 개념을 정복해보고자 한다.

 

Preview

 

좋은 관계형 데이터베이스를 설계하는 목적 중 하나는 정보의 이상(Anomaly) 현상이 생기지 않도록 하는 것이다.

 

데이터베이스에는 대표적으로 3가지 현상이 존재한다.

  • Insertion anomalies(삽입 이상)

: 삽입 이상은 원하지 않는 자료가 삽입된다든지, 삽입하는데 자료가 부족하여 삽입이 되지 않는 문제를 의미한다.

  • Deletion anomalies(삭제 이상)

: 삭제 이상은 하나의 자료만 삭제하고 싶지만, 그 자료가 포함된 튜플 전체가 삭제됨으로 원하지 않은 정보 손실이 발생되는 문제를 의미한다.

  • Modification anomalies(갱신 이상)

: 갱신 이상은 정확하지 않거나 일부의 튜플만 갱신되어 정보가 모호해 지거나 일관성이 없어져 정확한 정보를 파악할 수 없는 문제를 의미한다.

 

위의 3가지 데이터베이스의 이상 현상들은 대부분 정규화를 통해 해결이 가능하다.

 

정규화(Normalization)

 

정규화는 테이블 간의 중복된 데이터를 허용하지 않는 것을 의미한다. 테이블 정규화를 통해 데이터 무결성을 유지하고 데이터베이스의 저장 용량을 줄일 수 있게 된다.

 

데이터베이스 정규화는 크게 1NF, 2NF, 3NF, BCNF로 구분이 된다.

 

제 1정규화(1NF)

 

제 1정규화 정규화는 테이블 컬럼의 도메인 값이 모두 atomic한 값을 갖도록 테이블을 분해하여 중복되는 그룹을 제거하는 것을 의미한다.

아래 예시는 1NF의 예시이다. 아래의 경우, 1001, 1002번이 한 컬럼에 중복된 값을 갖고 있는 것을 확인할 수 있다. 제 1정규화는 이러한 중복된 값을 가지고 있는 것을 atomic한 값을 갖도록 테이블을 분해하는 것을 의미한다.

 

제 2정규화(2NF)

 

제 2정규화는 제 1정규화를 만족하면서, 기본키에 속하지 않는 속성 모두가 기본키에 완전 함수 종속하도록 테이블을 분해하는 것을 의미한다. 여기서 완전 함수 종속이란, 기본키의 부분 집합이 결정자가 되어서는 안된다는 의미라고 해석할 수 있다.

아래 예시는 제 2정규화의 예시로 복합키로 구성된 함수적 의존성의 결정자 부분의 부분집합 A가 C의 결정자 역할을 하게 되는 것을 확인할 수 있다. 이때, 테이블 내에서 이러한 부분적 함수 종속성을 제거해주어야 한다.

 

제 3정규화(3NF)

 

제 3정규화란, 제 2정규화의 조건을 만족시키면서 이행적 함수 종속성을 제거해 테이블을 분해하는 것을 의미한다. 즉, 기본키 이외의 속성이 그 외 다른 속성을 결정하는 경우 테이블을 분해하는 것을 의미한다.

아래 예시의 경우, 기본키 A 이외에 B->C의 함수적 종속성이 존재하는 것을 확인할 수 있다. 이때, 제 3정규화 원칙에 따라 이행적 함수 종속성을 제거하여 테이블을 분해해주어야 한다.

 

BCNF

 

BCNF 정규화는 우리가 일반적으로 가장 많이 진행하는 정규화 작업으로 제 3정규화를 진행한 테이블에 대해 모든 결정자가 후보키가 되도록 테이블을 분해하는 것을 의미한다.

아래 예시를 보면 복합키 겸 기본키인 A, B 이외에 D->B의 함수적 종속성을 가진 것을 확인할 수 있다. 이런 경우, 모든 결정자가 후보키가 되도록 테이블을 분해해주어야 한다.

 

 

비정규화(Denormalization)

 

정규화가 데이터의 효율적인 저장을 위해서 필요한 작업은 맞지만, 무조건 적으로 정규화가 옳은 작업은 아닐 때가 있다. 그런 경우에는 비정규화 작업을 진행한다. 비정규화는 정규화 작업을 통해 득볼 수 없는 경우에 사용한다. 즉, 어느 정도의 데이터 중복이나 그로 인해 발생하는 데이터 갱신 비용은 어느 정도 감수하는 대신, 조인의 횟수를 줄여 효율적인 쿼리를 날릴 수 있도록 하는 작업을 의미한다.

 

비정규화 같은 경우 아래와 같은 상황에서 사용하면 유용하다.

  • 자주 사용되는 테이블에 접근하는 프로세스의 수가 많고, 항상 일정한 범위만을 조회하는 경우.
  • 테이블에 대량 데이터가 있고 대량의 범위를 자주 처리하는 경우, 성능상 이슈가 있을 경우.
  • 테이블에 지나치게 조인을 많이 사용하게 되어 데이터를 조회하는 것이 기술적으로 어려운 경우.

 

위와 같은 상황에서 비정규화를 진행하게 되면 데이터를 조회할 때 속도는 조금 느릴지 몰라도 한층 더 효율적인 쿼리를 날릴 수 있을 것이다.

 

그러나, 비정규화를 과도하게 적용하게 되면 데이터의 무결성이 깨질 수 있고 Insert/Modification/Delete 쿼리에 대한 응답 시간이 지나치게 길어질 수 있기에 주의하며 사용할 필요가 있다.