데이터베이스의 정규화란 무엇이며, 왜 필요한가?
데이터베이스의 정규화란 관계형 데이터베이스를 설계할 때나오는 개념입니다.
관계형 데이터베이스란 쉽게 말해서 실제 존재하는 개념을 개체(Entity)로 만들어 개체간의 관계(Relationship)를 만들어주는 것을 말합니다.
학생이라는 Entity와 관계(Relation)된 Entity에 대해서 예를 들어보자면 스터디그룹, 전공학과일 것입니다.
이렇게 각 개체와 개체간의 관계를 테이블 등으로 표현하는 것을 데이터베이스라고 합니다.
예를 들어 학교라는 시스템을 데이터베이스로 표현한다면 우선 학생이란 개체(Entity)가 필요할 것입니다.
학생이라는 Entity에는 <이름>, <나이>, <학번>, <전공>과 같은 속성들을 가지게 될 것입니다.
이를 토대로 학생 테이블에 데이터가 구성하게 되면
이름 |
나이 |
학번 |
전공 |
김아무개 |
21 |
201501012 |
컴퓨터공 |
이런식의 하나의 표, 그러니까 테이블이 만들어 질 것입니다.
김아무개 뿐만 아니라 홍길동의 데이터가 추가되면 김아무개의 다음 행에 홍길동과 함께 한 행을 채우게 되겠죠.
여기서 학생이라는 개념을 테이블(다른 말로, 릴레이션, Relation)
이름, 나이, 학번, 전공를 열(다른 말로, 어트리뷰트, Attribute)
그리고 김아무개의 정보가 담긴 한 행을(다른 말로, 튜플, Tuple)이라고 합니다.
또, 전공이라는 열을 예로 들어보면 컴퓨터공, 경영학, 기계공학... 등등 채워질 수 있는 내용들이 있게 됩니다.
이 속성을 이루는 값들의 집합을 도메인(Domain)이라고 합 니다.
테이블 = 릴레이션, 열 = 어트리뷰트 .... 짜증납니다. 똑같은 개념에 대한 단어가 여러 가지입니다.
아무튼 이렇게 누구나 알 법한 데이터베이스에 대한 기초상식에 대해서 이야기 한 이유는
데이터베이스를 설계하면서 필요한 정규화의 개념에 대해서 이야기하고 싶어서 입니다.
학생 테이블 뿐만 아니라 수강생 테이블을 하나 더 생각해봅니다.
수강생 테이블에는
<학번>, <이름>, <나이>, <전공>, <재수강여부> 등등의 정보가 들어갈 수 있겠죠
학번 |
이름 |
나이 |
전공 |
재수강여부 |
201501012 |
김아무개 |
21 |
컴퓨터공 |
True |
201502039 | 홍길동 | 22 | 경영학과 | False |
뭔가 비효율적이지 않나요?
학교 시스템이라는 전체 시스템에서 학생, 수강생의 예만 들어봐도 저렇게 중복되는 정보가 있습니다.
<학번>, <이름>, <나이>, <전공> 등은 학생 테이블이나 수강생 테이블에 중복되어 존재하게 됩니다.
그렇지만 학생이라는 객체와 수강생이라는 객체는 엄연히 분리되어 할 개념이긴 한데 말이죠.
비효율적이라고 말한 이유는 간단합니다. 테이블이 수정되거나 삽입 될 때에는 모든 테이블에 걸쳐서 연쇄적으로 수정되거나 삽입되어야 합니다. 단 두가지의 테이블만 봐서 그렇지 어떠한 시스템에서는 이런식으로 데이터베이스가 짜져있다면 최소 수십개의 테이블에 데이터를 삽입하던지 수정해야 될 것입니다. 데이터의 일관성을 유지하기 위해서 말이죠.
이러한 상황을 해결하기 위해 정규화(Nomalization) 라는 것이 필요한 것입니다.
기본적으로 정규화란 잘못설계된 데이터베이스의 구조를 더 작은 속성으로 쪼개어 바람직한 구조로 만드는 과정입니다.
* 여기서 번외로 하나 설명해보자면, 결국 정규화 과정을 거치게 되면서 한데 뭉쳐있던 테이블을 더 잘게 쪼개게 되어 테이블의 수가 더 많아지게 됩니다. 이렇게 쪼개어진 정보에서 의미있는 정보를 추출해내기 위해서는 서로 합치는 과정을 통해 출력 결과를 도출해내는 연산이 필요한데, 이를 관계형 데이터베이스에서는 JOIN이라고 부릅니다. 이 JOIN 연산시 상당히 큰 부하를 가져오게 됩니다. 물론 그렇다고 정규화를 안한 데이터베이스를 사용하진 않습니다. 보통 성능과 이상증상의 제거를 고려하여 적당한 선에 결정합니다.(Trade Off)
정규화의 방법에는 여러가지가 있습니다.
1NF, 2NF, 3NF, BCNF, 4NF, 5NF 등 많이 있으나 (NF = Normal Form, 정규형) 성능상의 이슈등을 고려해 보통 3NF나 BCNF정도에서 멈춘다고 합니다.
(성능을 위해 이미 정규화된 테이블을 합치는 것을 역정규화라고 합니다)
제1 정규화(= 1NF)
모든 속성은 원자값을 가진다. 하나의 컬럼에는 두 개의 값이 들어 갈 수 없다는 것입니다.
위의 테이블은 니콜라스라는 사람이 가지는 취미가 자전거, 독서인데, 한 컬럼에 두 개의 값이 들어가있습니다. 이러한 구조는 제1정규화의 대상입니다. 다음과 같이 수정합니다.
제2 정규화(= 2NF)
Key 외의 다른 컬럼들은 Key에만 의존적이어야 한다. (완전 함수 의존)
이 말이 처음에는 잘 이해가 안됐는데, 쉽게 정리해보자면
키(중심이자 유일한 성질을 갖는 컬럼) 이외의 일부 컬럼에 의해 결정되는 컬럼들이 있으면
안된다는 말이다.
예를 들어 학교라는 테이블을 생각해보자.
<"학교"테이블>
key값이 학번, 수강과목에 있다. 학번과 수강과목을 통해 행의 유일성은 보장 할 수 있겠지만 제2정규화를 만족할 수 없다. (키에 의존적이지 않은 컬럼들이 존재한다)
학생이름과 학년 학과는 학번에 종속적인 컬럼입니다. 종속적이라는 것은 학번이라는 값을 통해 결정되는 컬럼을 뜻합니다.
의존적이라는 말이 오히려 더 이해하기 쉬운 듯하지만 혼용해서 사용하겠습니다.
이에 반해 학점, 교수, 개설학과는 수강과목에 종속적인 컬림입니다. 결국 학점, 교수, 개설학과는은 학번에 의존적인 컬럼이 아니라는 이야기입니다. 마찬가지로 학생이름, 학년, 학과도 수강과목에 의존적이지 않은 컬림이죠.
다음과 같이 수정해야 합니다.
<"학생"테이블>
<"수강과목"테이블><"수강"테이블>
이와같이 변하면 각 컬럼들은 해당 테이블의 키값에만 종속적이게 됩니다.
제3 정규화(= 3NF)
기본키에 의존하지 않고, 일반키에 의존적인 컬럼들을 제거합니다.
보통 책에는
"이행종속이 있으면 안된다. 단, Key가 아닌 어느 속성이 Key의 일부를 결정지을 수 있다면 3NF를 만족"
"이행종속이란? A->B, B->C 결정하는 경우 A->C를 결정" 이렇게 설명되어 있는데
이게 도대체 무슨말인가...싶습니다. 쉽게 이해가 되지 않습니다.
첫 번째 줄이 더 이해 잘 될 것 같습니다.
기본키에 의존하는 키에 또 다른 컬럼이 의존하는 것. 즉 A -> B, B -> C 와 같이 설명한 것을 이해할 수 있겠습니다.
제2정규화된 결과에서 수강과목 테이블에 주목합니다. 수강과목 학점 교수 개설학과로 이루어져 있습니다.
교수는 수강과목에 의존적인 테이블 컬럼이고, 개설학과는 교수에 의존적인 테이블 컬럼입니다. 즉, 제3정규화의 대상이라는 말입니다. 다음과 같이 바꾸어줍니다.
<"학생"테이블>
<"수강과목"테이블>
<"교수"테이블>
<"수강"테이블>
이렇게 하면 3NF를 만족한다.(이행종속이 없다)
BCNF
BCNF의 주요 내용은 모든 결정자는 반드시 Key이어야 한다는 것입니다.
1NF에서 곧 바로 BCNF 정규화가 가능합니다.
학번 -> 이름, 학년, 학과
과목 -> 학점, 교수
교수 -> 개설학과
이렇게 키를 규정할 수가 있습니다.
제 4정규화
함수종속이 아닌 다치 종속 제거
제 5정규화
후보키를 통하지 않은 조인 종속성을 제거