reference: "데이터베이스 개론" / 김연희 / 한빛아카데미
DB를 잘못 설계하면 불필요한 데이터 중복, 잘못된 종속 관계가 발생하여 릴레이션에 대한 데이터의 삽입/수정/삭제 연산을 수행할 때 부작용들의 발생할 수 있다. 이러한 부작용을 이상 현상이라 한다. 이상 현상을 제거하면서 DB를 올바르게 설계해 나가는 과정이 정규화이다.
이상 현상에는 삽입 이상, 갱신 이상, 삭제 이상이 있다.
잘못된 DB 설계 결과물(이벤트 참여 릴레이션)을 바탕으로 각 이상 현상의 설명을 이어나간다.
source: https://overcome-the-limits.tistory.com/513
위 릴레이션에서 한 고객이 여러 이벤트에 참여할 수 있으므로 고객 아이디만으로는 튜플을 유일하게 식별할 수 없다. 그러므로 이벤트 참여 릴레이션의 기본키를 (고객 아이디, 이벤트 번호) 속성을 함께 사용하여 구성하였다.
고객 한 명이 여러 이벤트에 참여할 수 있으므로 이벤트 참여 릴레이션에는 동일한 고객의 이름과 등급이 중복적으로 나타날 수 있다. 이렇게 동일한 데이터가 여러 번 중복되어 저장되면 저장 공간을 낭비할 뿐 아니라, 릴레이션에 데이터를 삽입/수정/삭제할 때 삽입/갱신/삭제 이상 현상이 발생할 수 있다.
새 데이터를 삽입하기 위해 불필요한 데이터도 함께 삽입해야 하는 문제
source: https://overcome-the-limits.tistory.com/513
위 그림과 같이 고객 아이디가 melon, 이름이 성원용인 신규 고객이 가입하여, 해당 릴레이션에 이 고객에 대한 데이터를 삽입하려는 상황이다. 만약 이 고객이 참여한 이벤트가 아직 없다면 데이터를 삽입할 수 없다. 해당 릴레이션의 기본키에 이벤트 번호 속성이 포함되어 있고, 이 속성 값은 널(Null)로 지정할 수 없기 때문이다(개체 무결성 제약조건). 따라서 이 고객의 데이터를 삽입하려면 실제로 참여하지 않은 임시 이벤트 번호를 삽입해야하므로 삽입 이상이 발생한다.
중복 튜플 중 일부만 변경하여 데이터가 불일치하게 되는 모순의 문제
source: https://overcome-the-limits.tistory.com/513
위 그림과 같이 아이디가 apple인 고객의 등급이 gold에서 vip로 변경된다면, 이벤트참여 릴레이션에서 apple 고객에 대한 튜플 세 개의 등급 속성 값이 모두 수정되어야 한다. 그렇지 않다면 같은 고객이 서로 다른 등급을 가지는 모순이 생겨 갱신 이상이 발생하게 된다.
튜플을 삭제하면 꼭 필요한 데이터까지 함께 삭제되는 데이터 손실의 문제
source: https://overcome-the-limits.tistory.com/513
위 그림과 같이 아이디가 orange인 고객이 이벤트 참여를 취소하면 해당 릴레이션에 관련된 튜플을 삭제될 것이다. 그런데 이 튜플은 아이디가 orange인 고객이 참여하고 있는 이벤트에 대한 정보만 가지고 있는 것이 아니라 해당 고객에 대한 정보인 고객아이디/고객이름/등급에 대한 정보도 '유일하게' 가지고 있다. 따라서 이 튜플이 삭제되면 이벤트 참여와 관련이 없음에도 불구하고 해당 고객에 대한 고객아이디/고객이름/등급 데이터까지 원치 않게 손실되는 삭제 이상이 발생하게 된다.
reference: 면접을 위한 CS 전공지식 노트/주홍철/길벗
"정규화 과정은 릴레이션 간의 잘못된 종속 관계로 인해 DB 이상 현상이 일어나서 이를 해결하거나, 저장 공간을 효율적으로 사용하기 위해 릴레이션을 여러 개로 분리하는 과정"
위 '이벤트 참여 릴레이션'에 여러 이상 현상이 발생하는 이유는 관련이 없는 데이터, 즉 속성들을 하나의 릴레이션에 모아두고 있기 때문이다. 이상 현상이 발생하지 않도록 하려면 관련있는 속성들로만 릴레이션을 구성해야 하는데 이를 위해 필요한 것이 정규화이다. 정규화는 이상 현상이 발생하지 않도록, 릴레이션을 관련이 있는 속성들로만 구성하기 위해 릴레이션을 분해(decomposition)하는 과정이라 할 수 있다. 바로 이 정규화를 통해 올바른 릴레이션의 설계를 완성할 수 있다.
정규화를 수행하려면 속성들 간의 관련성을 판단해야 한다. 바로 이 고려해야 할 관련성을 함수적 종속성(functional dependency)라고 한다. 일반적으로 릴레이션에 함수적 종속성이 하나 존재하도록 정규화를 통해 릴레이션을 분해한다.
하나의 릴레이션을 구성하는 속성들의 부분 집합을 X와 Y라 할 때, 어느 시점에서든 릴레이션 내의 모든 튜플을 대상으로 한 X 값에 대한 Y 값이 항상 하나면 "X가 Y를 함수적으로 결정한다" 또는 "Y가 X에 함수적으로 종속되어 있다"고 한다. 이 때 X를 결정자, Y를 종속자라고 한다.
source: https://overcome-the-limits.tistory.com/513
위 그림에서의 고객 릴레이션을 살펴보면, 각 고객아이디 속성 값에 대응되는 고객이름 속성과 등급 속성의 값이 단 하나이므로, 고객아이디가 고객이름가 등급을 결정한다고 볼 수 있다. 따라서 고객 릴레이션에서 고객이름과 등급 속성은 고객아이디 속성에 함수적으로 종속되어 있고, 고객아이디는 결정자가 되고, 고객이름과 등급은 종속자가 된다.
이 관계를 아래와 같이 '함수 종속 다이어그램'으로 도식화 할 수 있다.
일반적으로 튜플을 유일하게 구별하는 '기본키'와 '후보키'는 그 특성에 의해 릴레이션을 구성하는 다른 모든 속성들을 함수적으로 결정한다. 하지만 이러한 특성으로 인해 함수 종속 관계에서 기본키나 후보키만 결정자가 될 수 있는 것은 아니다. 이 외에도 다른 속성 집합을 유일하게 결정하는 속성 집합이 존재한다면 모두 결정자가 될 수 있다.
※ 주의 사항
함수 종속 관계를 판단할 때 현재 시점에 릴레이션에 포함된 속성 값만으로 판단해서는 안된다. 릴레이션에서 속성 값은 계속 변할 수 있기에 속성 자체가 가지고 있는 특성과 의미를 기반으로 판단해야 한다. 즉 속성 값이 아닌 속성 자체의 특성을 고려하여 함수 종속 관계를 판단해야 한다.
일단 상황을 간소화하기 위해 '등급' 속성이 없는 릴레이션을 살펴본다.
이벤트 참여 릴레이션에서는 고객 아이디가 고객 이름을 유일하게 결정한다. 따라서 고객 이름은 고객 아이디에 종속되어 있고, 고객 아이디가 결정자, 고객 이름이 종속자가 된다.
함수 종속 관계 1. 고객 아이디 -> 고객 이름
그리고 기본키인 (고객 아이디, 이벤트 번호) 속성 집합은 당첨여부 속성을 유일하게 결정한다. (고객 아이디, 이벤트 번호) 속성 집합이 결정자, 당첨여부 속성이 종속자가 된다.
함수 종속 관계 2. (고객 아이디, 이벤트 번호) -> 당첨여부
추가로 다음과 같은 종속 관계도 있다.
(고객 아이디, 이벤트 번호) -> 고객 이름
위 종속 관계들에서 고객 이름은 (고객 아이디, 이벤트 번호)에 종속됨에 동시에 일부분인 고객 아이디에도 종속되어 있다. 이러한 경우 고객 이름 속성이 (고객 아이디, 이벤트 번호) 속성 집합에 "부분 함수 종속"되었다 한다. 반면 당첨여부 속성의 경우 (고객 아이디, 이벤트 번호) 속성 집합 전체에 종속되어 있는데 이런 경우는 "완전 함수 종속"되었다 한다.