정규화 논리

RDB를 잘 다루는데 필요한 기술이고 관계형 모델을 전제로 구추괸 DB 설계 이론이다.

변칙

데이터가 논리적인 불일치가 일어나는 상태를 모순이라고 한다. 이를 변칙이라고도 하는데 변칙을 방지하는 것이 정규화의 역할이다. 변칙이 발생하는 주요 원인은 중복이기도 한데 사소한 갱신의 실수로 모순이 생길수가 있다. 때문에 중복을 줄여야 더 좋은 상태로 만들 수 있고 정규화의 주된 목적이기도 하다.

정규형

정규화를 하는데 각 단계를 거치게 된다.

  1. 제1 정규형(1NF)
  2. 제2 정규형(2NF)
  3. 제3 정규형(3NF)
  4. 보이스코드 정규형(BCNF)
  5. 제4 정규형(4NF)
  6. 제5 정규형(5NF)
  7. 제6 정규형(6NF)

DB설계에서 중요한 것은 BCNF와 5NF이다.

제1 정규형(1NF)

1NF는 정규화의 출발점이다. 1NF를 하기 위한 요건은 “릴레이션이어야 할 것”이다.

다음은 테이블이 1NF가 되기 위한 요건이다.

  1. 행이 위에서 아래로 정렬돼 있지 않다.
  2. 열이 왼쪽에서 오른쪽으로 정렬돼 있지 않다.
  3. 중복하는 행이 존재하지 않다.
  4. 각 행과 열의 교차점(즉 열의 값)은 도메인(데이터형)에 속하는 요소의 값을 딱 한 개만 가진다.
  5. 모든 열의 값은 정의된 것이어야 하고 각 행은 항상 존재한다.

칼럼이나 행의 순서

SQL의 사양에서는 테이블의 칼럼의 순서가 존재하기 때문에 1NF를 만족하지 않는다. 그러나 실제 질의에서 칼럼이나 행의 위치에 의존되지 않게 사용되면 문제가 되지 않는다. 칼럼의 순서에 의존하는 질의는 다음과 같은 것들이 있다.

  • SELECT *로 모든 칼럼의 값을 검색하고 응용프로그램이 칼럼의 위치에 따라 데이터에 접근하는 것
  • ORDER BY 절의 인수로 SELECT LIST 내에서 칼럼의 위치를 지정하는 것(ORDER BY 1같은)

중복되는 행을 제거

단순히 똑같은 행이 1개 넘게 존재하지 않으면 된다. 테이블에 기본키나 유니크키가 고유성 제약 조건을 붙이면 된다.

그러나 중요한건 제약이 아니라 실제로 저장되는 값이 중복되지 않게 해야한다는 것이다.

NULL이 포함되면 안 된다

테이블의 모든 행, 칼럼은 구체적인 값을 가져야 한다. 단순히 NOT NULL 제약을 건다고 해결되지 않는다. NOT NULL 제약을 걸면 응용프로그램이 칼럼의 값이 불분명하다고 판단하므로 기본값을 할당한다. 예를 들어 나이에 대한 칼럼은 -1이나 1000의 값을 가질 수가 있다. NULL을 없애기 위한 가장 좋은 방법은 테이블을 나누는 것이다. 칼럼의 값이 NULL 이라는 것은 아직 데이터가 필요로 하는 단계가 아니기 때문이다. 따라서 그 칼럼이 그 테이블에 있을 필요는 없다.

값의 원자성

원자값, 즉 더 이상 분리할 수 없는 값을 말한다. 더 분리할 수 없는 값으로 분리하는 것은 애매한 값이다. 주소값을 예로 들자면 주소가 원자성을 지니는지 아니면 시/군/구로 나누는게 원자성을 가지는지는 명확한 답을 얻을 수가 없다.

명확한 것은 의미가 있는 한 묶음의 데이터를 한 단위로 취급해야 한다는 것이다. 이메일 주소의 경우 이메일을 쪼개 버리면 그 문자열은 의미가 없어지게 된다.

그렇다면 의미가 있는 묶음이란 무엇인가? 이를 바탕으로 하는 중요한 개념이 도메인이다. 도메인은 속성이 가질 수 있는 값의 집합이다. 집합의 요소는 그 이상 분해할 수 없는 원자이다. 집합의 요소가 원자이므로 도메인의 요소 중 하나로 속해 있으면 원자라는 요건을 충족할 수 있다. 즉 의미가 있는 데이터는 도메인의 요소 중 하나라고 바꿔 말할 수 있다.

애매한 부분은 값의 열의 값이 될 가능성이 있는 집합, 즉 도메인 중에서 골라낸 요소의 하나라고 정의하면 혼란은 없다. 열의 값으로 어떤 것이 맞는지는 응용프로그램의 역할이다. 응용 프로그램이 처리할 수 있는 데이터 형식이 어떤 것인지 생각하는 것, 즉 도메인의 설계가 DB설계의 첫 걸음이다.

1NF의 오해가 되는 것은 1NF의 요건은 열의 값이 스칼라여야 한다라는 것이다. 실제로는 데이터 종류에는 특별한 제한이 없고, 집합으로 표현할 수 있는 것이면 어떤 값이든 상관이 없다. 벡터든 배열이든 스칼라든 집합의 도메인이 될 수 있기 때문이다.

반복 그룹

1NF 조건을 만족하지 않는 테이블의 예로 반복그룹이 있다. 반복 그룹은 4의 조건을 만족하지 않는 것으로 한 개의 열에 여러 개의 값을 콤마 등의 구분자로 나누어 할당한 것이다. 이와 같은 칼럼 내의 값을 나누어서 연산해야 하므로 관계형 모델을 기반으로 논리를 만들 수가 없다.

후보키와 슈퍼키

  • 후보키 : 릴레이션에 포함된 튜플의 값을 고유하게 하는 속성의 집합으로 기약을 말한다. 기약이란 더는 속성을 줄일 수 없는 상태를 말한다. 후보라고 불리는 이유는 튜플의 값을 고유하게 요구하는 속성의 집합이 한 종류밖에 없는 것은 아니기 때문이다.

    SQL에는 기본키라는 개념이 있지만 관계형 모델에는 기본키의 개념이 없다.

    후보키가 아닌 속성은 키가 아닌 속성이라고 한다.

  • 슈퍼키 : 후보키의 슈퍼셋, 즉 추가 속성을 가지는 슈퍼키라고 한다. 슈퍼키도 튜플의 값이 고유하다는 점에서 후보키와 같다. 단순하게 추가(고유한 값을 구하는 데 도움되지 않는) 속성을 가지고 있을 뿐이다. 후보키는 슈퍼키의 일종이며 속성의 수가 최소한이라고 할 수 있다. 릴레이션은 중복된 튜플이 없어야 하므로 반드시 후보키가 존재하며 제목 전체에는 모든 속성이 포함되므로 제목은 반드시 슈퍼키가 되어야 한다.

함수 종속성(FD)

2NF ~ BCNF는 함수 종속성에 관한 정의이며 전부 함수 종속성을 이용해 설명할 수 있다. 그리고 함수 종속성을 최대한 배제한 것이 BCNF이다.

함수 종속성(FD): 어떤 릴레이션 R이 있고, 제목의 부분집합 두 개를 A, B라고 한다. 릴레이션 R의 모든 튜플이 A의 값이 같다면 B의 값도 같은 경우가 있을 수 있다. 이 경우에 한해서 B는 A에 함수 종속한다고 하고, 이러한 관계성을 A→B라고 기술한다.

쉽게 말해 A값을 알면 B의 값을 알 수 있다는 의미이다. A 값이 다르고 B의 값이 같아도 문제는 없다. B는 중복이 허용된다.

릴레이션의 임의의 속성은 그 슈퍼키에 함수 종속한다. 즉 SK를 어떤 릴레이션의 슈퍼키라고 하고 X를 그 릴레이션의 임의의 속성이라고 하면 SK→X이다. 또, 임의의 제목 조합이 있을 때 그 부분집합은 원래의 제목에 함수 종속한다. 예를 들어 x, y라는 두 개의 속성이 있을 때 {x, y} → {x} 또는 {x, y} →{y}가 성립된다.

이러한 함수 종속성은 함수 종속성의 정의에서 필연적으로 도출되므로 자명한 함수 종속성이라고 한다. 자명한 함수 종속성은 릴레이션에서 제외할 수가 없다. 문제가 발생하는 것은 자명하지 않은 함수 종속성이다.

함수 종속성이란 키의 성질을 정의한 것이라고 볼 수 있다. 일반적으로 키의 값이 정해지면 같은 튜플에 포함된 임의의 속성값을 구할 수 있다. 예를 들어 A→B라는 함수 종속성을 가지고 있으면 A는 그 릴레이션의 키가 아니므로 반복해서 나타난다. 정의에 있는 것처럼 A의 값이 같다면 B의 값도 같다는 것이 숨겨진 키(자명하지 않은 함수 종속성)의 성질을 나타낸다. 2NF~BCNF는 이처럼 자명하지 않은 함수 종속성을 없애는 작업이다.

제2 정규형(2NF)

2NF는 후보키의 진부분집합에서 키가 아닌 속성에 함수 종속성을 제거하는 작업이다. 진부분집합이란 부분집합 중에 원래 자신의 집합을 제외한 것을 말한다. 이런 함수 종속성을 부분 함수 종속성이라고 한다. 릴레이션이 1NF이며 부분 함수 족속성을 갖지 않으면 그 릴레이션은 2NF가 된다. 키에 포함된 속성이 한 개밖에 없을 때는 공집합 외에 키의 진부분집합이 존재하지 않는다. 따라서 1NF이며 후보키가 한 개의 속성으로 된 릴레이션은 자동으로 2NF가 된다.

무손실 분해

함수 종속성을 해결하려고 릴레이션을 여러개로 분리하는 작업이다. 작업을 할 때 필요한 것은 프로젝션이다. 원래의 정보를 잃어버리지 않으면서 분해하는 것이라 무손실 분해라고 한다. 분해된 릴레이션을 재구축해야 원래의 릴레이션이 나오는데 이 때 사용되는 작업을 조인이라고 한다. 무손실 분해가 가능한지의 기준이 되는 것이 종속성이다.

제3 정규형(3NF)

추이 함수 종속성을 제거하는 작업이다.

추이 함수 종속성은 키가 아닌 속성이 함수 종속성을 이루고 있는 경우이다. 키가 아닌 두 속성 A, B가 A→B가 존재한다고 할 때, 슈퍼키를 알면 A가 정해지고 A가 정해지면 B도 정해지는 것을 말한다.

보이스코드 정규형(BCNF)

BCNF는 자명하지 않은 함수 종속성이 모두 제거된 상태의 정규형이다. 따라서 이 이상 함수 종속성에 의한 무손실 분해는 할 수 없다.

2NF는 (숨겨진 키)자명하지 않은 함수 종속성이 모두 제거된 정규형

3NF는 키가 아닌 속성의 다른 키가 아닌 속성의 종속성이 제거된 정규형

남아있는 패턴은 키가 아닌 속성에서 후보키의 진부분집합에 대한 함수 종속성이다.

예를들어 이름, 학과, 연구실이라는 릴레이션이 존재한고, 후보키는 {이름, 학과}이다. 여기서 연구실이 학과보다 자세한 정보라는 점이고 연구실을 알면 학과를 알 수 있다. {연구실}→{학과}의 함수종속성을 가진다. 그렇기 때문에 {이름, 연구실}을 후보키로 잡을 수도 있다. 물론 {이름, 학과}가 후보키가 될 수도 있다. 이렇게 3NF이기도 하지만 BCNF가 될 수 없는 릴레이션은 후보키가 되는 속성의 조합이 여러 개 존재한다. {이름, 연구실}로 키를 정하게 되면 {연구실}→{학과}로 자명하지 않은 함수 종속성이 존재하게 된다. 그렇기에 {이름, 연구실}, {연구실, 학과}로 프로젝션 할 수 있게 된다.