안녕하세요.
오늘은 데이터베이스 정규화에 대해 알아보겠습니다.
- 정규화
'관계형 데이터베이스의 설계에서 중복을 최소화하게 데이터를 구조화하는 프로세스를 정규화(Normalization)라고 한다. 데이터베이스 정규화의 목표는 이상이 있는 관계를 재구성하여 작고 잘 조직된 관계를 생성하는 것에 있다.'
위의 정의가 일반적인 정규화의 정의 입니다.
데이터에 중복을 제거하고 삽입이상, 갱신이상, 삭제이상이 나타나지 않도록 테이블을 설계하는게
정규화라고 생각하면 될 것 같습니다.
- 제1정규형
제 1정규형은 한 릴레이션을 구성하는 모든 도메인이 원자값만으로 구성되도록 하는 정규형을 말합니다.
이름 | 취미 |
철수 | 축구, 야구, 농구 |
영희 | 농구, 배구 |
민수 | 골프, 축구, 탁구 |
위와 같은 테이블은 취미 칼럼에 여러개의 데이터가 들어있습니다.
제 1정규형에서는 한개의 칼럼에는 하나의 데이터만 들어가야합니다.
위 테이블은 제1정규형에 의해 아래와 같이 정규화됩니다.
이름 | 취미 |
철수 | 축구 |
철수 | 야구 |
철수 | 농구 |
영희 | 농구 |
영희 | 배구 |
민수 | 골프 |
민수 | 축구 |
민수 | 탁구 |
- 제2정규형
'후보 키 K와 K에 속하지 않는 속성 A가 있을 때, A를 결정하기 위해 K의 일부가 아닌 K 전체를 참조해야만 하는 경우 1NF 테이블은 2NF이다.'
후보키가 복합키(다중칼럼)로 설정되어 있을 때 복합키의 일부칼럼에 다른칼럼들이 결정되어서는 안된다는 뜻입니다.
정의에서 후보키로 설명을 하지만 대체적으로 테이블을 정규화 할때 3정규형을 기본으로 합니다.
3정규형에서 종속관계를 기본키에 대해서만 허용하므로 후보키가 아닌 기본키로 생각해도 상관이 없습니다.
(어차피 후보키의 종속관계는 3정규형에서 제거되므로)
'pk가 다중칼럼일때 pk의 일부칼럼에 다른 칼럼들이 결정되면 안된다' 라고 이해해도 될 것 같습니다.
참고로 제1정규형 테이블의 기본키가 복합키가 아닌 단일키이면 자동으로 제2정규형을 만족합니다.
이름 | 나이 | 탄생화 | 취미 |
권나라 | 25 | 장미 | 발레 |
한소희 | 28 | 백합 | 연기 |
권나라 | 20 | 개나리 | 댄스 |
아이린 | 27 | 튤립 | 댄스 |
한소희 | 25 | 장미 | 연기 |
위와 같이 개인정보와 탄생화, 취미를 저장하는 테이블이 있다고 하겠습니다.
일단 단일칼럼들은 중복이 있어 후보키가 될 수 없습니다.
후보키는 (이름,나이), (나이,탄생화), (이름, 탄생화), (나이, 취미), (탄생화, 취미)가 될 수 있겠네요.
기본키를 (이름, 나이)로 설정하겠습니다.
(이름, 나이)에 의해 탄생화가 결정되니 pk가 다른 컬럼을 결정한다고 할 수 있겠네요.
그런데 여기에서 자세히 보면 나이에 의해서도 탄생화가 결정됨을 알 수 있습니다.
pk가 다중컬럼인데 pk의 일부속성에 다른 속성이 결정되고 있습니다.
제2정규형에 위반되는 테이블입니다.
위의 테이블을 제2정규형을 거치면 아래와 같이 테이블을 설계할 수 있습니다.
사실 여기에서 정규형을 멈추면 제2정규형의 결함이 있을 수 있습니다.
우리는 기본키에 대해서만 제2정규형 기준을 맞추었는데 제2정규형은 후보키에 대해서 기준을 맞춰야 하죠.
3정규형을 간다면 3정규형에서 어차피 제거 되므로 굳이 따져보지 않아도 되지만
여기서는 따져 보겠습니다.
이름, 나이, 취미 테이블의 후보키는 (이름, 나이), (나이, 취미) 입니다.
(이름, 나이)에 대해 이름이나 나이가 취미를 결정하는지 따져 보겠습니다.
권나라 -> 발레
권나라 -> 댄스 //같은 이름에 대해 다른 취미값 나옴
25 -> 발레
25 -> 연기 //같은 나이에 대해 다른 취미 나옴
이름, 나이 각각 취미를 결정짓지 못하네요.
(나이, 취미)에 대해 나이나 취미가 이름을 결정하는지 따져보겠습니다.
25 -> 권나라
25 -> 한소희 //같은 나이에 대해 다른 이름값 나옴
댄스 -> 권나라
댄스 -> 아이린 //같은 취미에 대해 다른 이름값 나옴
나이, 취미도 이름을 결정하지 못하네요.
위의 테이블은 제2정규형을 만족한다고 할 수 있습니다.
- 제3정규형
제3 정규형이란 데이터베이스 정규화의 세 번째 단계로, 다음 조건을 만족해야 한다:
- 테이블이 제2정규형을 만족
- 테이블 내의 모든 속성이 기본 키에만 의존하며, 다른 후보 키에 의존하지 않는다.
- 이행함수 종속이 존재 하지 않는다.
네, 위의 개념을 압축하면 '기본키 외의 다른 속성은 종속관계를 가질수 없다는 뜻' 입니다.
주민번호 | 이름 | 나이 | 탄생화 |
930123-1****** | 개코 | 29 | 장미 |
750123-2****** | 민지 | 47 | 백합 |
830123-2****** | 쌈자 | 39 | 튤립 |
830123-1****** | 개코 | 39 | 튤립 |
위와 같은 테이블이 있다고 하겠습니다.
pk는 주민번호입니다. 주민번호가 이름, 나이, 탄생화를 모두 결정합니다.
그런데 나이도 탄생화를 결정하네요.
함수 종속을 따져보면
X(주민번호) -> Y(나이), Y(나이) -> Z(탄생화) 에 의해 X(주민번호) -> Z(탄생화) 라는 관계가 성립되네요.
이러한 경우를 이행함수 종속이라고 합니다. 3정규형에서는 이행함수 종속을 제거해야합니다.
정규화를 하면 위와 같이 테이블이 나뉠수 있겠네요.
- 보이스코드 정규화
관계형 데이터베이스의 릴레이션 R에서 함수 종속성 X→Y가 성립할 때, 모든 결정자 X가 후보키이면 BCNF 정규형이 된다. 즉, 식별자로 쓰이는 속성이 일반속성에 종속되지 않아야 한다. 제3정규화를 통해서도 제거되지 않은 데이터의 중복 문제를 해결해 주기 때문에 일명 ‘제3.5정규화’라고도 부른다.
이름 | 사는곳 | 팀 | 등번호 |
호나우도 | 맨체스터 | 맨유 | 7 |
메시 | 바르셀로나 | 바르샤 | 10 |
음바페 | 파리 | 파리생제르망 | 10 |
테베스 | 맨체스터 | 맨시티 | 9 |
호나우도 | 파리 | 파리생제르망 | 11 |
위 테이블의 기본키가 (이름, 사는곳) 이라고 할때 (이름, 사는곳)은 팀을 결정합니다.
맨체스터에 사는 호나우도는 맨유에서 뛰고,
파리에 사는 호나우도는 파리생제르망에서 뛰고,
파리에 사는 음바페도 파리생제르망에서 뜁니다.
그런데 여기에서 팀과 사는곳 사이 관계를 보면 팀이 사는곳을 결정하는걸 알 수 있습니다.
맨유에서 소속된 선수는 맨체스터에서 살고 있습니다.
맨유 -> 맨체스터
바르샤 -> 바르셀로나
파리 -> 파리생제르망
맨시티 -> 맨체스터
반대의 경우 사는곳이 팀을 결정 하지는 못합니다.
맨체스터 -> 맨유
맨체스터 -> 맨시티 라는 경우가 있기 때문이죠.
보이스코드의 경우 복합키의 일부가 다른 속성에 종속되는 경우를 제거하는 것입니다.
여기서 제2정규형과 헷갈릴수 있는데 제2정규형은 복합키의 일부가 다른속성을 결정하는 것을 제거하지만
BCNF의 종속 제거 방법은 우선
BCNF를 위반하는 종속관계(X -> Y)의 칼럼에 대해 따로 테이블을 만들어주고
팀 | 사는곳 |
맨유 | 맨체스터 |
바르샤 | 바르셀로나 |
파리생제르망 | 파리 |
맨시티 | 맨체스터 |
위반하는 X를 제외한 나머지 속성들로 이루어진 칼럼들로 테이블을 하나 만들어줍니다.
이름 | 사는곳 | 등번호 |
호나우도 | 맨체스터 | 7 |
메시 | 바르셀로나 | 10 |
음바페 | 파리 | 9 |
테베스 | 맨체스터 | 9 |
호나우도 | 파리 | 11 |
위처럼 두개의 테이블이 생성되면 됩니다.
위 테이블은 pk가 팀, 아래테이블은 pk가 (이름, 사는곳)으로 구성될 수 있겠죠.
정규형의 절차를 하나씩 따라가다보면 굉장히 까다로워 보일 수 도 있는데요.
각 정규형의 개념을 알고 3차정규형, 보이스코드 정규형이 목표라고 한다면
단계별로 거치지 않고 바로 3차 또는 BCNF 정규형으로 진행할 수 도 있습니다.
'DB' 카테고리의 다른 글
git 명령프롬프트를 통한 사용법(git 명령어 사용법) (0) | 2020.10.29 |
---|---|
이클립스 프로젝트와 깃허브(github) 연동방법 (0) | 2020.10.27 |
[Database] 키의 개념과 구분(슈퍼키, 후보키, 기본키, 대체키, 외래키) (0) | 2020.09.29 |
함수 종속성(완전 함수 종속, 부분함수 종속, 이행함수 종속)의 개념 (2) | 2020.09.12 |
mysql workbench 설치 및 사용법(오류해결 mysql 5.*버전 사용자) (0) | 2020.09.12 |