Home 데이터베이스 정규화
Post
Cancel

데이터베이스 정규화

정규화 과정

  • 릴레이션 간의 잘못된 함수 종속관계로 인해 데이터베이스 이상 현상이 일어나는 것을 해결하는 과정
  • 저장 공간을 효율적으로 사용하기 위해 릴레이션을 여러 개로 분리하는 과정

이상현상(anomaly)?

데이터베이스 설계를 잘못했을 때 불필요한 데이터 중복이 발생하여 릴레이션에 대한 데이터의 삽입, 갱신, 삭제 연산을 수행할 때 부작용이 발생하는 것을 말한다. 조회의 경우에는 문제가 발생하진 않는다.

예를 들어보자.

위와 같은 테이블이 있다고 가정한다.

삽입 이상

불필요한 데이터도 같이 삽입해야 하는 문제이다.

예를 들어 윤성용, yun이 가입했다고 하자. 가입할 때 이벤트를 참여 안하는 경우가 있다.

이렇게 null 값과 함께 들어가게 된다.

갱신 이상

중복 레코드가 있고 이 중 일부만 변경해 데이터 자체가 불일치되는 문제

주홍철의 등급이 플래티넘으로 승급했음에도 일부만 수정하게 된다.

골드, 골드, 골드였지만 첫 레코드만 갱신이 되어 데이터가 불일치된다.

삭제 이상

레코드를 삭제하는데 필요한 데이터까지 함께 삭제되는 문제.

만약 변정훈이 이벤트 참여를 취소한다면?

이벤트번호 및 당첨여부만 지우고 싶은데 해당 행을 다 지워야한다.

그래서

이렇게 관련없는 속성들이 하나의 릴레이션에 모였을 때 발생하는 것이 이상현상이다. 이를 해결하는 척도가 되는 것이 함수종속이다.

릴레이션간의 관련성을 함수 종속성을 통해 파악하고 이를 기준으로 릴레이션을 분리하는 정규화 과정을 진행해야 한다.

함수적 종속성

어떤 릴레이션을 구성하는 속성의 부분집합이 X, Y라고 할 때 하나의 X에 대해 Y가 하나라면 X가 Y를 함수적으로 결정한다 또는 Y가 X에 함수적으로 종속되어 있다. 라는 관계를 갖는 것을 말한다.

X는 결정자, Y는 종속자가 된다.

예시

아이디는 이름과 등급을 결정한다. 로그인은 아이디를 기반으로 이루어지고, 이는 아이디를 통해 이름과 등급이 결정된다고 볼 수 있는 것이다.

zagabi인 아이디를 가진 고객은 이름이 주홍철이고, 등급이 골드인 사람 딱 하나뿐이다.

즉 이름과 등급은 아이디에 함수적 종속성을 갖는다.

이 때 릴레이션의 속성 값을 기반으로 결정하면 안되고, 속성 자체의 특성을 기반으로 결정해야 한다.

여기서 아이디는 고객을 구별해주는 “기본키” 특성을 가지고 아이디가 같은 서로 다른 고객은 존재할 수 없다. 그렇기 때문에 아이디가 결정되면 이름과 등급이 결정되게 된다.

여기서 X -> Y 라는 관계에서 기본키나 후보키가 아니더라도 결정자인 X가 될 수 있다.

완전함수종속과 부분함수종속

여기서 이벤트에 관한 부분을 집중해보자.

  • [아이디, 이벤트 번호] -> 당첨여부
  • 아이디 -> 이름

이라는 관계를 가진다.

완전함수종속은 Y가 X전체에 종속된 것이고, 부분함수종속은 Y가 X 일부에 종속된 것이다.

즉, 위의 예시에서는 이름은 아이디에 완전 종속되어있는 것이고,

[아이디, 이벤트번호] 에는 부분종속 되어 있는 것이다. 이름은 아이디에만 완전 함수 종속이 되어있기 때문이다.

[아이디, 이벤트번호]는 당첨여부와 완전함수종속 되어있다고 볼 수 있다.

제 1정규형

릴레이션의 모든 도메인이 더 이상 분해될 수 없는 원자 값으로만 구성되어야 한다.

릴레이션의 속성 값 중 한 개의 기본키에 대해 두 개 이상의 값을 가지는 반복 집합이 있다면 제거하는 것을 의미한다.

물론 아래와 같이 바꾸면 이상현상이 발생할 수 있다.

일단 제 1정규형은 이렇게 하나의 기본키에 여러 개의 값을 갖지 못하도록 분해된 상태를 말한다.

제 2정규형

릴레이션이 제 1정규형이며 기본키가 아닌 모든 속성이 기본키에 완전 함수 종속된 것을 말한다.

  • 기본키 : 아이디

위의 테이블은 등급이 아이디에 종속, 할인율이 등급에 종속되어 있다.

그리고 [아이디, 이벤트 번호]에 당첨 여부가 종속되어 있다.

이렇게 부분함수종속 되어있는 부분을 떼어내는 것이다.

무손실분해

이러한 정규화과정에서 중요한 부분은 분해한 릴레이션은 조인이 가능해야하고, 조인이 되었을 때 분해 전의 릴레이션들로 복원이 가능해야 한다.

즉 분해했을 때 정보 손실이 발생하지 않아야 한다.

제 3정규형

제 2정규형이고 기본키가 아닌 모든 속성이 기본키에 이행적 함수 종속만족하지 않는 상태를 의미한다.

이행적 함수 종속

A -> B와 B -> C가 존재하면 논리적으로 A -> C가 성립하는데, 이 때 집합 C가 집합 A에 이행적으로 함수 종속이 되었다고 한다.

예를 들어보자.

등급은 아이디에 종속되어있고, 할인율은 등급에 종속되어 있으므로 할인율은 아이디에 이행적 종속되어있다.

이를 위와 같은 고객 릴레이션, 아래와 같은 등급 릴레이션으로 나누어 기본키에 이행적 종속되는 부분이 없도록 만들 수 있다.

만약 이렇게 나누지 않는다면 골드 등급의 할인율을 수정해야 할 때 골드인 유저의 행을 모두 수정하게 된다.

보이스/코드 정규형

제 3정규형이고, 모든 결정자가 후보키인 상태를 말한다.

보통 하나의 릴레이션에 여러 개의 후보키가 존재할 수 있는데 이 경우 제 3정규형보다 엄격한 기준으로 제약을 건 것이 보이스/코드 정규형이다.

예를 들어보자.

  • 각 수강명에 대한 한 학생은 오직 한 강사의 강의만 수강한다.
  • 각 강사는 한 수강명만 담당한다.
  • 한 수강명은 여러 강사가 담당할 수 있다.

[학번, 수강명] 또는 [학번, 강사]가 후보키가 된다.

만약 [학번, 수강명]이 기본키라고 했을 때, [학번, 수강명]은 강사를 결정한다.

하지만 이 경우 강사는 후보키가 아님에도 불구하고 수강명을 결정하는 결정자 역할을 하게 된다. 그래서 아직 학번이 정해지지 않았을 때 null이 들어가는 삽입 이상현상이 발생할 수 있다.

이를 이렇게 나눌 수 있다. 여기에는 만약 수강명이 롤이고 강사가 범석이지만 아직 듣는 학생이 없을 때 null 값이 같이 들어가는 이상현상을 해결할 수 있다.

정규화 과정의 필요성

이 외에도 고급정규형 4,5 정규형도 있다.

정규화 과정은 결국 릴레이션(테이블)을 나누는 과정인데, 테이블을 나누게 되면 성능이 좋아질 수도, 나빠질 수도 있다.

예를 들어 어떤 쿼리의 경우 테이블을 나누어버린 경우 “조인”을 계속해서 해야하기 때문에 오히려 느려질 수 있다.

따라서 서비스에 따라 정규화, 비정규화 과정을 진행해야 한다.

정규화 과정은 중복 데이터가 제거됨에 따라 스토리지에 대한 전체 메모리 요구량이 감소하게 되고 오류가 발생할 가능성이 줄어든다.

비정규화 과정은 조인 자체가 발생하는 코스트가 크기 때문에 조인이 많이 필요한 쿼리가 많아진다면 어느정도의 비정규화가 필요하다.

This post is licensed under CC BY 4.0 by the author.

서블릿, JSP 그리고 이 둘로 만드는 MVC 패턴

MVC 프레임워크 제작(프론트 컨트롤러의 도입)