데이터베이스 개론 2판 내용을 참고하여 작성하였습니다.
정규화
관련 없는 속성을 하나의 릴레이션에 모아두면 문제가 발생할 수 있습니다. 데이터베이스에서 싫어하는 데이터 중복이 많이 나타나고, 예기치 못한 일들이 발생할 수 있습니다. 싫어하는 음식을 먹지 않는 것처럼 릴레이션에 관련 없는 속성이 들어가지 않게 하고, 친한 속성끼리 릴레이션을 구성해주면 됩니다.
속성들의 친밀도를 판단하고, 이 기준에 따라 릴레이션을 구성하는 방법이 정규화입니다. 또한 데이터베이스를 설계한 후 설계 결과물을 검증하기 위해 사용하기도 합니다.
데이터베이스를 잘못 설계하면 불필요한 데이터 중복이 발생하여 릴레이션에 대한 데이터의 삽입, 수정, 삭제 연산을 수행할 때 부작용이 발생할 수 있습니다. 이러한 부작용을 이상(anomaly) 현상이라고 합니다.
이상 현상의 종류
이상 현상에는 삽입 이상, 갱신 이상, 삭제 이상이 있습니다.
삽입 이상 : 새 데이터를 삽입하기 위해 불필요한 데이터도 함께 삽입해야 하는 문제
갱신 이상 : 중복 튜플 중 일부만 변경하여 데이터가 불일치하게 되는 모순 문제
삭제 이상 : 튜플을 삭제하면 꼭 필요한 데이터까지 함께 삭제되는 데이터 손실 문제
위 그림은 고객들이 이벤트에 참여한 결과를 저장하고 있는 릴레이션입니다.
고객에 대한 정보인 고객아이디, 고객이름, 등급과 고객이 참여한 이벤트에 대한 정보인 이벤트 번호와 당첨여부를 포함하고 있습니다.
한 고객은 여러 이벤트에 참여할 수 있으므로 고객 아이디만으로는 튜플을 유일하게 식별할 수 없습니다. 그러므로 이벤트 참여 릴레이션의 기본키를 고객 아이디와 이벤트 번호 속성을 함께 사용하여 구성합니다.
고객 한 명이 여러 이벤트에 참여할 수 있으므로 이벤트 참여 릴레이션은 동일한 고객의 이름과 등급이 여러 번 나타날 수 있습니다. 아이디가 apple인 고객은 3개의 이벤트에 참여하므로 고객 이름과 등급이 이벤트 참여 릴레이션에 세 번 저장되고 있습니다. 이렇게 동일한 데이터가 여러 번 중복 저장되면 저장 공간을 낭비할 뿐 아니라 릴레이션에 데이터를 삽입, 수정, 삭제할 때 삽입, 갱신, 삭제 이상 현상이 발생할 수 있습니다.
삽입 이상
릴레이션에 새 데이터를 삽입하기 위해 원치 않는 불필요한 데이터도 함께 삽입해야 하는 문제를 삽입 이상이라고 합니다. 이벤트 참여 릴레이션에 신규 고객의 데이터를 삽입해야할 때 이 고객이 참여한 이벤트가 아직 없다면 이벤트 참여 릴레이션에 이 고객에 대한 데이터를 삽입할 수 없습니다.
이벤트 참여 릴레이션의 기본키가 고객 아이디와 이벤트 번호 속성이고, 기본키를 구성하는 속성은 null 값을 가질 수 없다는 제약이 존재하기 때문입니다. 고객 아이디와 참여한 이벤트 번호가 모두 존재해야 이벤트 참여 릴레이션에 고객 데이터를 삽입할 수 있습니다. 이 고객에 대한 데이터를 이벤트 참여 릴레이션에 삽입하려면 임시 이벤트 번호를 삽입해야하므로 이벤트 참여 릴레이션에는 삽입 이상이 발생하게 됩니다.
갱신 이상
릴레이션의 중복된 튜플 중 일부만 수정하여 데이터 불일치가 발생하는 것을 갱신 이상(update anomaly)이라고 합니다. 위의 이벤트 참여 릴레이션에는 아이디가 apple인 고객에 대한 튜플이 3개 존재하여 고객 아이디, 고객 이름, 등급 속성의 값이 중복되어 있습니다.
아이디가 apple인 고객의 등급이 변경된다면 이벤트 참여 릴레이션에서 apple 고객에 대한 튜플의 등급 속성 값은 모두 수정되어야 합니다. 그렇지 않고 일부 튜플만 수정된다면 apple 고객이 서로 다른 등급을 가지는 모순이 생겨 갱신 이상이 발생합니다.
삭제 이상
릴레이션에서 튜플을 삭제할 때 필요한 데이터까지 함께 삭제하여 데이터가 손실되는 현상을 삭제 이상(deletion anomaly)이라고 합니다. 고객이 이벤트 참여를 취소하여 이벤트 참여 릴레이션에서 관련 튜플을 삭제해야하지만, 해당 고객에 대한 정보인 고객 아이디, 고객 이름, 등급에 대한 정보도 가지고 있습니다. 따라서 이 튜플이 삭제되면 이벤트 참여와 관련 없는 해당 고객 데이터까지 손실되는 삭제 이상이 발생하게 됩니다.
정규화의 필요성
이러한 이상 현상이 발생하는 이유는 무엇일까요? 관련 없는 데이터, 관련 없는 속성을 하나의 릴레이션에 모아두고 있기 때문입니다. 이상 현상이 발생하지 않도록 하기 위해서는 관련 있는 속성들로만 릴레이션을 구성해야 합니다.
이 때 필요한 것이 정규화입니다. 정규화는 이상 현상이 발생하지 않도록 릴레이션을 관련 있는 속성들로만 구성하기 위해 릴레이션을 분해하는 과정입니다.
정규화를 수행하려면 먼저 릴레이션을 구성하는 속성들 간의 관련성을 판단할 수 있어야 합니다. 정규화 과정에서 고려해야 하는 속성들 간의 관련성을 함수적 종속성(FD: Functional Dependency)이라고 합니다. 일반적으로 릴레이션에 함수적 종속성이 하나만 존재하도록 정규화를 통해 릴레이션을 분해합니다.
함수 종속
하나의 릴레이션을 구성하는 속성들의 부분 집합을 X와 Y라고 할 때, 어느 시점에서든 릴레이션 내의 모든 튜플에서 하나의 X 값에 대한 Y 값이 항상 하나면 "X가 Y를 함수적으로 결정한다" 또는 "Y가 X에 함수적으로 종속되어 있다" 라고 합니다.
함수 종속 관계는 X -> Y로 표현하고 X를 결정자, Y를 종속자라고 합니다.
고객 아이디와 고객 이름, 등급 값이 저장된 고객 릴레이션이 있습니다. 각 고객 아이디 속성 값에 대응되는 고객 이름 속성과 등급 속성 값이 단 하나이므로, 고객 아이디가 고객 이름과 등급을 결정한다고 볼 수 있습니다. 예를 들어 고객 아이디가 apple인 고객은 이름이 정소화, 등급이 gold인 한 사람만 있습니다.
그러므로 고객 릴레이션에서 고객 이름과 등급 속성은 고객 아이디 속성에 함수적으로 종속되어 있으며, 고객 아이디는 결정자가 되고 고객 이름과 등급은 종속자가 됩니다.
함수 종속 관계를 판단할 때 현재 시점 릴레이션에 포함된 속성 값만으로 판단하면 안 됩니다. 릴레이션에서 속성 값을 변할 수 있기 때문에 속성 자체가 가지고 있는 특성과 의미를 기반으로 판단해야 합니다.
위의 고객 릴레이션에서 함수 종속 관계를 판단할 때, 고객 릴레이션에서 고객 아이디는 고객을 구별해주는 기본키 속성이기 때문에 아이디가 같은 서로 다른 고객이 존재할 수 없습니다. 그러므로 고객 아이디가 정해지면 오직 하나의 고객 이름과 등급이 결정됩니다.
일반적으로 튜플을 유일하게 구별하는 기본키와 후보키는 그 특성 때문에 릴레이션을 구성하는 다른 모든 속성들을 함수적으로 결정합니다. 하지만 이러한 특성으로 인해 함수 종속 관계 X -> Y에서 기본키나 후보키만 결정자인 X가 될 수 있는 것은 아닙니다. 릴레이션의 여러 튜플에서 속성 X 값이 같으면 이 값과 연관된 속성 Y 값도 모두 같으면 결정자가 될 수 있습니다. 이처럼 기본키나 후보키가 아니더라도 함수 종속 관계에서 결정자가 될 수 있습니다.
완전 함수 종속과 부분 함수 종속
위의 이벤트 참여 릴레이션에서는 고객 아이디가 고객 이름을 유일하게 결정합니다. 고객 아이디가 같으면 모든 튜플에서 고객 이름이 반드시 같은 값을 가지기 때문입니다. 그러므로 고객 아이디는 결정자, 고객 이름은 종속자가 됩니다.
기본키인 [고객 아이디, 이벤트 번호] 속성 집합은 당첨 여부 속성을 유일하게 결정합니다. 아이디가 apple인 고객이 참여한 E001 이벤트의 당첨여부는 Y만 존재하기 때문입니다. 그러므로 당첨 여부는 [고객 아이디, 이벤트 번호]에 종속되어 있어, [고객 아이디, 이벤트 번호]가 결정자가 되고 당첨 여부가 종속자가 됩니다. 이 때 당첨 여부뿐만 아니라 고객 이름도 기본키인 [고객 아이디, 이벤트 번호]에 종속되어 있습니다.
이벤트 참여 릴레이션에 존재하는 함수 종속 관계에서 [고객 아이디, 이벤트 번호]에 종속되어 있는 고객 이름은 [고객 아이디, 이벤트 번호]의 일부분인 고객 아이디에도 종속되어있습니다. 이런 경우, 고객 이름 속성이 [고객 아이디, 이벤트 번호] 속성 집합에 부분 함수 종속(PFD : Partial Functional Dependency)되었다고 합니다.
당첨 여부 속성은 [고객 아이디, 이벤트 번호]의 일부분이 아닌 속성 집합 전체에 종속되어 있습니다. 이런 경우에는 당첨 여부 속성이 [고객 아이디, 이벤트 번호] 속성 집합에 완전 함수 종속(FFD : Full Functional Dependency)되었다고 합니다.
완전 함수 종속은 릴레이션에서 속성 집합 Y가 속성 집합 X에 함수적으로 종속되어 있지만, 속성 집합 X 전체에 종속된 것이지 일부분에 종속된 것이 아닙니다. 부분 함수 종속은 속성 집합 Y가 속성 집합 X의 전체가 아닌 일부분에도 함수적으로 종속됨을 의미하기에 부분 함수 종속 관계가 성립되기 위해서는 결정저가 여러 개의 속성들로 구성되어야 합니다.
일반적으로 함수 종속이라고 하면 완전 함수 종속을 의미합니다.
기본 정규형과 정규화 과정
함수 종속성을 이용하여 릴레이션을 연관성 있는 속성들로만 구성되도록 분해하여 이상 현상이 발생하지 않는 릴레이션으로 만드는 과정을 정규화(normalization)라고 합니다. 정규화의 기본 목표는 관련이 없는 함수 종속성은 별개의 릴레이션으로 표현하는 것입니다.
릴레이션이 정규화된 정도는 정규형(NF : Normal Form)으로 표현합니다. 정규형은 크게 기본 정규형과 고급 정규형으로 나뉩니다. 기본 정규형에는 제1정규형, 제2정규형, 제3정규형, 보이스/코드 정규형이 있고, 고급 정규형에는 제4정규형, 제5정규형이 있습니다.
각 정규형마다 만족시켜야 하는 제약조건이 존재합니다. 릴레이션이 특정 정규형의 제약조건을 만족하면 릴레이션이 해당 정규형에 속한다고 표현합니다. 정규형의 차수가 높아질수록 요구되는 제약조건이 많아지고 엄격해집니다.
차수가 높은 정규형에 속하는 릴레이션일수록 데이터 중복이 줄어 데이터 중복으로 인한 이상 현상이 발생하지 않는 릴레이션일 수 있습니다. 하지만 모든 릴레이션이 제5정규형에 속해야 하는 것은 아니며 릴레이션의 특성을 고려하여 적합한 정규형을 선택해야 합니다.
일반적으로 기본 정규형에 속하도록 릴레이션을 정규화합니다.
'데이터베이스' 카테고리의 다른 글
정규화의 종류 (1) | 2022.11.04 |
---|---|
트랜잭션(Transaction)이란 (16) | 2022.07.24 |