티스토리 뷰
제 1 정규형부터 Boyce-Codd 정규형 알아보기
정규화와 정규형
정규화는 데이터의 중복을 최소화하고, 데이터의 일관성을 지키기 위해 사용되는 관계형 데이터베이스 설계 이론입니다.
정규형은 정규화 과정에서 테이블이 만족해야 하는 특정 규칙을 나타내는 개념으로, 정규화와는 구별해야 합니다.
정규화는 쉽게 말하면, 관계형 스키마를 더 작은 속성들로 분해해 가는 과정이라고 할 수 있습니다.
주의해야 할 점은 테이블을 의미( = 함수적 종속 관계 )에 맞게 나누어야 하며
추후 데이터 손실이 발생하지 않아야 한다는 거죠.
정규화는 아래와 같은 장점을 가져다줍니다.
- 이상 현상을 제거하여 데이터를 일관성 있게 보존할 수 있게 합니다.
- 정규화가 되어 있는 쪽이 현실 세계와의 관계를 더 잘 반영합니다.
- 데이터 중복이 최소화되니 더욱 적은 용량으로 관리할 수 있습니다.
- 새로운 테이블이나 칼럼을 추가하거나 또는 칼럼 수정할 때 수정으로 인한 영향이 최소화됩니다.
이상 현상
정규화가 이루어지지 않으면 아래와 같은 이상현상이 발생할 수 있습니다.
- 삽입 이상(insertion anomalies) : 잘못된 데이터가 들어가거나 또는 들어가지 않는 일이 발생하는 것
- 삭제 이상(deletion anomalies) : 정규화가 되어 있지 않아 특정 정보를 삭제하기 위해 전체가 삭제되는 것
- 수정(갱신)이상(modification anomalies) : 일부만 수정되거나 정보의 일관성이 파괴되는 것
정규화의 단점과 반정규화
정규화를 하면 데이터 중복이 최소화되기 때문에 더 속도가 빨라진다는 장점이 있지만, 반대 상황도 있습니다.
테이블이 잘게 나뉘게 되면 데이터 조회 시 JOIN이 필요하게 될 수 있습니다. 이는 오히려 쿼리를 느려지게 하죠.
따라서 의도적으로 정규화는 반 정규화라는 방법을 사용합니다.
아래는 반 정규화가 사용되는 경우입니다.
- 자주 사용되는 테이블에 액세스 하는 프로세스의 수가 가장 많고, 항상 일정한 범위만을 조회하는 경우
- 테이블에 대량 데이터가 있고 대량의 범위를 자주 처리하는 경우, 성능 상 이슈가 있을 경우
- 테이블에 지나치게 조인을 많이 사용하게 되어 데이터를 조회하는 것이 기술적으로 어려울 경우
따라서 데이터 베이스를 설계할 때에는 어떤 데이터냐에 따라, 자주 사용되는 쿼리 로직에 따라
적절히 정규화와 반정규화를 사용하는 것이 좋습니다.
정규형
정규형은 여러 가지가 있는데요. 일반적으로 제 1, 2, 3형 Boyce-Codd까지가 사용됩니다.
이어서 예시와 함께 직접 테이블을 분리하면서 정규형들을 살펴보겠습니다.
쇼핑몰의 주문내역을 저장하는 테이블이 있다고 해봅시다.
테이블은 주문번호, 고객 번호, 주문날짜, 제품번호를 가지고 있습니다.
주문 번호(PK) | 고객 번호 | 주문 날짜 | 제품 번호 | 제품명 |
1, 4 | 101 | 2024-03-01, 2024-03-04 | 1 ,3 | 제품1, 제품3 |
2 | 102 | 2024-03-02 | 2 | 제품2 |
3 | 103 | 2024-03-03 | 1 | 제품1 |
제 1 정규형 (1NF)
애트리뷰트의 도메인이 오직 원자값만을 포함하고, 튜플의 모든 애트리뷰트가 도메인에 속하는 하나의 값을 가져야 한다.
즉, 복합 애트리뷰트, 다중값 애트리뷰트, 중첩 릴레이션 등 비 원자적인 애트리뷰트들을 허용하지 않는 릴레이션 형태를 말한다.
제 1 정규형은 엑셀과 같은 형태로써,
각 애트리뷰트 ( = 엑셀에서는 셀이라 하는 부분 )가 하나의 값을 가져야 한다는 것을 의미합니다.
또한 이 값은 도메인 ( = 칼럼의 타입 )에 속하는 값이어야 합니다.
위에서 고객번호 101의 데이터는 다중값 애트리뷰트에 해당됩니다. 여러 개의 값을 한 번에 가지고 있는 거죠.
원자적 속성이 아닌 겁니다. 이를 분리하면 다음과 같습니다.
주문테이블
주문 번호(PK) | 고객 번호 | 주문 날짜 | 제품 번호 | 제품명 |
1 | 101 | 2024-03-01 | 1 | 제품1 |
2 | 102 | 2024-03-02 | 2 | 제품2 |
3 | 103 | 2024-03-03 | 1 | 제품1 |
4 | 101 | 2024-03-04 | 3 | 제품3 |
이제 테이블이 원자적 속성들로 구성되었으므로 제 1 정규형을 만족한다고 할 수 있습니다.
제 2 정규형 (2NF)
모든 비주요 애트리뷰트들이 주요 애트리뷰트에 대해서 완전 함수적 종속이면 제 2 정규형을 만족한다고 볼 수 있다.
완전 함수적 종속이란 X -> Y 라고 가정했을 때, X 의 어떠한 애트리뷰트라도 제거하면 더 이상 함수적 종속성이 성립하지 않는 경우를 말한다. 즉, 키가 아닌 열들이 각각 후보키에 대해 결정되는 릴레이션 형태를 말한다.
함수적 종속성이라는 건 하나의 키에 나머지가 종속되어야 한단 뜻입니다.
쉽게 모든 비주요 속성이 주요 키에 종속되어야 한다는 의미인데요.
이전 예시를 보면 주문번호(PK)와는 무관하게 제품번호가 존재할 수 있는 것을 볼 수 있습니다.
즉, 제품번호가 주문번호에 종속되지 않음으로, 위 테이블은 완전 함수 종속을 만족하지 못하는 거죠.
따라서 제품번호를 별도의 테이블로 나눠줄 필요가 있습니다.
주문테이블
주문 번호(PK) | 고객 번호 | 주문 날짜 |
1 | 101 | 2024-03-01 |
2 | 102 | 2024-03-02 |
3 | 103 | 2024-03-03 |
4 | 101 | 2024-03-04 |
제품테이블
제품 번호(PK) | 제품명 |
1 | 제품1 |
2 | 제품2 |
3 | 제품3 |
제품번호에 제품명이 종속되니 제품명도 함께 분리해 보았습니다.
이제 두 개의 테이블이 완전 함수 종속을 만족한다고 할 수 있겠네요.
제 3 정규형 (3NF)
어떠한 비주요 애트리뷰트도 기본키에 대해서 이행적으로 종속되지 않으면 제 3 정규형을 만족한다고 볼 수 있다. 이행 함수적 종속이란 X → Y, Y → Z의 경우에 의해서 추론될 수 있는 X → Z의 종속관계를 말한다. 즉, 비주요 애트리뷰트가 비주요 애트리뷰트에 의해 종속되는 경우가 없는 릴레이션 형태를 말한다.
글이 길지만 핵심 키워드는 이행 함수적 종속입니다.
예시를 바꿔서 수강신청 정보가 저장된 테이블이 있다고 해볼까요.
수강신청 테이블
학번 (PK) | 학생이름 | 수업 | 교수명 |
20240001 | 학생1 | 수업1 | 교수1 |
20240002 | 학생2 | 수업2 | 교수2 |
20240003 | 학생3 | 수업1 | 교수1 |
20240004 | 학생4 | 수업2 | 교수2 |
학번을 알면 그 학번의 학생이 어떤 수업을 듣는지 알 수 있습니다. (X → Y)
그리고 어떤 수업을 듣는지 알면 어떤 교수에게 수업을 듣는지 알 수 있죠. (Y → Z)
수업과 교수가 모두 하나의 학번(PK)에 종속된 것은 맞지만 여전히 종속이 존재합니다. (X →Z 이 추론된다.)
즉, 이행 함수적 종속이 존재합니다.
이 경우 같은 수업에 여러 명의 학생이 있을 때, 동일한 교수 이름이 중복으로 저장되겠죠.
또는 한 수업의 교수명이 변경될 경우, 수강신청 테이블의 모든 테이블에 대해 update가 필요한지 확인을 해야 할 겁니다.
update를 하다가 중간에 실패가 되면 수업명은 같은데 교수명은 다른 데이터 불일치가 생길 거고요.
이런 이상 현상을 방지하기 위해 이행 함수적 종속을 제거할 필요가 있습니다.
수강신청 테이블
학번 (PK) | 학생이름 | 수업번호 |
20240001 | 학생1 | 1 |
20240002 | 학생2 | 2 |
20240003 | 학생3 | 1 |
20240004 | 학생4 | 2 |
수업 테이블*
수업번호(PK) | 수업명 | 교수명 |
1 | 수업1 | 교수1 |
2 | 수업2 | 교수2 |
수강신청 테이블에서 수업과 교수를 수업 테이블로 분리했습니다.
이제 수강신청 시 수업번호 외에 교수명까지 적을 필요가 없게 되었네요.
또한 교수명이 바뀌더라도 해당 수업테이블의 데이터만 update 해주면 되겠죠.
*위의 수업테이블은 제 2형 정규형에 만족하지 않습니다. 각각 수업, 교수 테이블로 분리하거나(1), 수업명과 교수명을 복합키로 지정하는 방법(2)으로 완전 함수 종속으로 바꿀 수 있겠네요.
Boyce-Codd 정규형 (BCNF)
여러 후보 키가 존재하는 릴레이션에 해당하는 정규화 내용이다. 복잡한 식별자 관계에 의해 발생하는 문제를 해결하기 위해 제 3 정규형을 보완하는데 의미가 있다. 비주요 애트리뷰트가 후보키의 일부를 결정하는 부분을 분해하는 과정을 말한다.
Boyce-Code 정규형은 PK가 아닌 다른 키도 특정 행을 식별할 수 있다면 후보키로 정의하고, 후보키를 분해하는 것을 말합니다.
제 3정규형에서 후보키가 여러 개 존재하고 서로 중첩되는 경우에 적용합니다.
3NF를 달성하는 과정에서 테이블이 BCNF를 동시에 만족하기도 합니다.
3NF와 유사하지만, BCNF는 모든 결정자가 후보키인 경우를 보장하는 것에 중점을 둡니다. ⭐
감사합니다.
공부한 내용을 복습/기록하기 위해 작성한 글이므로 내용에 오류가 있을 수 있습니다.
'DB' 카테고리의 다른 글
[DB] MySQL의 락 (feat. Auto Increment Lock) (0) | 2024.03.10 |
---|---|
[DB] 락(Lock)과 트랜잭션 (0) | 2024.03.09 |
[DB] 인덱스(Index) (0) | 2024.03.07 |
[DB] SQL의 기본 문법 (0) | 2024.03.04 |
[DB] NoSQL과 레디스(Redis) (0) | 2023.12.07 |