속성 간 부정확한 종속성을 제거하는 것을 의미합니다.
유사한 속성들은 모으고 종속성이 없는 독립적인 속성들은 분리하는 것이 정규화 입니다.
관계형 데이터 모델이 되기 위해서는 속성의 종속성괴 의존성을 분석하여 분해될 수 없는 엔티티로 만드는 정규화 과정이 필요합니다.
데이터 통합과 엔티티 정의, 이력 데이터 관리 등은 정규화 단계에 포함됩니다. 정규화를 수행해야 데이터 성격에 맞는 엔티티가 도출됩니다. 그리고 데이터 성격에 맞는 엔티티가 도출되면 확장성이 좋은 모델이 됩니다.
정규형도 문제점이 존재하고 더 나은 선택을 위해 비정규형을 채택할 수도 있습니다. 하지만, 완벽한 정규형 모델은 실제 업무를 잘 반영할 수 있습니다.
정규화를 진행하는 근본적인 이유는 중복 데이터 (속성과 엔티티)를 제거하기 위해서입니다. 중복성은 데이터 정합성에 영향을 미치고 아노말리 현상을 발생시킵니다.
데이터 정체성이 반영된 모델 구조는 요구사항이 추가되어도 엔티티 반영이 수월합니다. 엔티티를 추가할지 속성을 추가할지 명확해지고 그에 따른 엔티티 관계도 명확해집니다.
정규형은 아노말리 현상을 최소화합니다.
아노말리는 데이터 이상 현상으로 업데이트 아노말리와 삭제, 삽입 아노말리 등이 존재합니다.
데이터 중복은 아노말리를 발생시키고 중복이 없는 정규형은 아노말리 최소화 시킵니다.
정규화를 이해하기 위해 함수 종속을 이해해야 합니다.
함수 종속은 관계형 모델을 설계할 때 중요한 데이터 종속성입니다. 데이터 종속성에는 함수 종속과 다가 종속, 조인 종속 등이 존재합니다. 대표적인 종속성은 함수 종속입니다.
릴레이션 내에 존재하는 속성 간 종속성을 의미합니다.
대표 속성(식별자)과 나머지 속성 사이의 연관 관계가 함수 종속입니다. A 속성의 값이 B속성의 값을 유일하게 식별할 수 있다면 B속성은 A 속성에 함수적으로 종속되었다고 표현합니다.
함수 종속은 속성 간의 종속성을 규명하여 집합을 분리해 속성과 엔티티를 정의하고 관계를 파악하는데 절대적 역할을 합니다.
함수 종속은 업무 요건을 알아야만 정확히 도출이 가능합니다. 그래서 속성이 엔티티에 속하는게 맞는 것인지 규명도 가능합니다. 함수 종속은 밀접한 속성을 모아 하나의 릴레이션으로 만드는 방법입니다.
정규화가 잘되었는지 함수 종속에 의해 집합이 잘 분해됐는지 좋은 모델을 구별할 수 있는 기준이 됩니다.
근거가 없는 집합으로 이루어진 모델은 좋은 모델이 될 수 없습니다.
속성간 종속성을 규명할 때 기준이 되는 값이 결정자입니다.
결정자에 의해 정해지는 값을 종속자라 합니다.
X : 결정자, Y : 종속자
결정자 X 값은 반드시 하나의 Y 값과 연관된다.
X값에 의존하는 Y 값은 하나 뿐이지 다른 Y는 있을 수 없다.
y = f(x) 라고 표현합니다.
예를들어 주민등록번호가 이름 등을 유일하게 결정한다 라고 이야기 할 수 있습니다.
X : 주민번호, Y : 이름
이름 하나에 주민번호가 여러개가 될 수 없습니다.
간략히 정리를 먼저하면
구분 | 제거대상 | 특징 |
1 정규화 | 다가 속성, 복합 속성, 반복 속성, 중첩 릴레이션 제거 | 속성이 추가되거나 일대다(1:M)관계의 릴레이션이 추가되며 관계를 상속시킴 |
2 정규화 | 부분 종속 제거 | 일대다(1:M) 관계의 릴레이션이 추가되며 관계를 상속받음 |
3 정규화 | 이행 종속 제거 | 일대다(1:M) 관계의 릴레이션이 추가되며 관계를 상속받음 |
BC 정규화 | 종속자가 키에 포함된 함수 종속 제거 | 모든 결정자는 Key이어야 한다는 관점에서 3정규화와 동일 |
4 정규화 | 다가 종속 제거 | 다가 속성의 개수만큼 일대다(1:M) 관계의 릴레이션이 추가됨 |
5 정규화 | 조인 종속 제거 | 조인 종속이 존재하는 릴레이션이 사용하기 편함. 지나치게 이상적인 정규형 |
1 정규형
한 속성에 여러 값을 갖는 릴레이션은 많이 업습니다. 하지만, 물리적으로 하나의 값을 가지고 있을 뿐 논리적으로는 여러 값을 가진 경우가 존재합니다.
같은 성격의 데이터를 여러 속성으로 나열해 관리하는 경우입니다.
row 1 = ID / 전화번호 컬럼 - BLUE / 123-456, 010-0000-0000
정규화를 진행하면 아래와 같이 단일 값을 갖는 속성으로 변경됩니다.
테이블 1 > ID / 전화번호 = BLUE / 123-456
테이블 1 > ID / 전화번호 = BLUE / 010-0000-0000
1 정규형을 진행하면
테이블 1 > ID / 집 전화번호 = BLUE / 123-456
테아블 2 > ID / 개인 연락처 = BLUE / 010-0000-0000
비정규형을 이용한다면
테이블 1 > ID / 집 전화번호 / 개인 전화번호 = BLUE / 123-456 / 010-0000-0000
위와 같이 비정규형을 채택한다면 속성에 의미를 명확히 부여하는 것이 중요합니다.
예를들어 전화번호1, 전화번호2, 전화번호3 과 같이 사용하는 것은 올바르지 않습니다.
전화번호 마다 테이블로 분해하는 것은 오히려 불편할 수 있습니다.
하지만, 주소의 경우 시, 구, 동을 구분해서 사용해야 하는 경우 동을 사용해서 집계 한다거나 자주 사용되면 분해하는 것이 좋습니다.
1 정규형 전 :
테이블 1 > ID / 이름 / 전화번호 / 시 / 구 / 동 / 번지
1 정규형 후 :
테이블 1 > ID / 이름 / 전화번호 / 주소
테이블 1 > ID / 이름 / 전화번호 / 주소 (시) / 주소 (구) / 주소 (동) / 주소 (번지)
구분 | ||
정규형 | 업무 요건 변경에 유연합니다. 확장성이 좋습니다. 인덱스 수가 감소하고 특정 요건 조회 시 SQL 단순합니다. 엔티티 속성 추가 가능성이 존재합니다. 로우 레벨로 관리되는 데이터 자식 엔티티를 가질 수 있습니다 |
|
비정규형 | 업무 요건의 변경에 매우 취약합니다. 모델 확장성이 좋지 않습니다. 인덱스 수가 증가하고 특정 요건 조회시 SQL 복잡해집니다. 엔티티 속성이 추가될 가능성이 없을 때 사용 가능합니다. 속성 레벨로 관리되는 데이터의 자식 엔티티를 가질 수 없습니다. |
비 정규형의 가장 큰 장점은 조회 성능이 좋아질 수 있습니다.
하지만 결과적으로 성능에는 좋지 못한 영향을 줄 수 있습니다.
2 정규형
릴레이션의 모든 속성이 후보 식별자 전체에 종속적이면 2 정규형입니다.
일반 속성 중 후보 식별자 전체에 종속적이지 않고 후보 식별자를 구성하는 속성 일부에 종속적인 속성이 있다면 중복이 발생한 것으로 릴레이션에서 분리해야 2 정규형이 됩니다.
2 정규화 대상은 후보 식별자를 구성하는 속성이 두 개 이상일 때만 대상이 되고, 단일 속성으로 후보 식별자가 구성되면 대상이 아닙니다. 두 개 이상의 속성이 후보 식별자로 구성된 경우 일반 속성 중에서 후보 식별자 전체에 종속적이지 않고 속성을 찾아 기본 엔티티에서 제거하고 그 속성의 결정자를 주 식별자로 하는 새로운 상위 엔티티를 생성하는 것이 2 정규화 입니다.
주문상품 Table = #주문번호, #상품코드, 상품명, 단가, 주문수량
위 모델과 같이 상품명과 단가는 주문상품 엔티티에서 제외하고 상품코드를 주 식별자로 하는 상품 엔티티를 상위 엔티티로 생성해야 2 정규형이 됩니다.
상품 Table = #상품코드, 상품명, 단가
주문상품 Table = #주문번호, #상품코드(FK), 주문수량
주문한 상품의 상품명을 알려면 상품 엔티티와 조인해야 하지만 이를 피하려고 상품명을 주문상품 엔티티에 중복시킨 것입니다. 이렇게 조인을 피하려 중복 속성을 사용하는 것은 지양해야 합니다.
3 정규형
이미 성립하는 종속성에서 새로운 종속성을 추론할 수 있는데 그 중 이행적 종속성이 있습니다.
만약 Y가 X에 종속되고 Z가 Y에 종속되면 Z는 X에도 종속된다고 추론하는 것입니다.
이때 Y는 릴레이션의 후보 식별자도 아니고 후보 식별자의 일부도 아닌 일반 속성입니다.
일반 속성(비식별 속성)간의 종속 관계를 분해하면 3 정규형이 됩니다.
일반 속성 간에는 서로 직접 종속될 수 없어 함수 종속 관계가 없어야 합니다.
3 정규형 대상이 되는 속성을 이해 종속 속성이라고 합니다.
일반 속성 사이에 결정자와 종속자 역할을 하는 속성이 존재하는 릴레이션은 3 정규화 대상입니다.
주문 Table = #주문번호, 고객ID, 고객명, 주문일자, 배송요청일자
후보 식별자가 아닌 일반 속성 간의 종속이 발생했으므로 고객명 속성은 주문 엔티티에서 삭제하고 고객 ID를 주 식별자로 하는 고객 엔티티를 생성하고 고객명 속성을 추가합니다. 그리고 새로운 엔티티 고객 엔티티와 주문 엔티티를 1:M 관계로 생성합니다.
고객 Table = #고객ID, 고객명
주문 Table = #주문번호, 고객ID(FK), 주문일자, 배송요청일자
2 정규형과 마찬가지로 중복 속성으로 3 정규형이 어긋난 경우가 많습니다.
조인을 피하려고 광범위하게 적용된 중복 속성은 제거해야 합니다.
보이스코드(BC) 정규형
3 정규형을 보강한 정규형입니다. 실무 적용에 이상적인 정규형 중 하나입니다.
BC 정규형은 모든 결정자는 주식별자가 되어야 합니다. 하지만, 이는 3 정규형에도 해당하는 정의로 3 정규형과 구분하면 릴레이션에 존재하는 종속자가 후보 식별자면 BC 정규형이 아니라고 설명할 수 있습니다.
만약 속성 Z에 종속된 Y가 후보 식별자에 포함된다면 BC 정규형이 아닙니다.
Y가 후보 식별자에 포함되는지에 따라 3 정규형과 BC정규형이 구분됩니다.
Y가 후보 식별자에 포함되어도 3 정규형 릴레이션은 만족하지만
BC 정규형 릴레이션은 만족하지 않습니다.
예를들어 학생의 학점을 관리하는 릴레이션입니다.
학생은 여러 과목을 수강하며, 교수는 한 과목만 강의할 수 있습니다.
FD1 = 학생번호, 과목명 >> 교수번호, 학점
FD2 = 교수번호 >> 과목
이 릴레이션 후보 식별자는 학생번화호와 과목명을 조합한 속성이거나 학생번호와 교수번호를 조합한 속성이 될 수 있습니다.
두 개 후보 식별자 중 학생번호화 과목명을 주 식별자로 선택했으므로 교수번호 속성은 일반 속성입니다.
하지만, FD2의 종속자인 과목명 속성이 주 식별자에 포함되어 있어 BC정규형이 어긋났습니다.
일반 속성인 교수번호가 주 식별자에 속한 과목명을 결정하므로 BC 정규형이 아닙니다.
수강과목 Table = 학생번호(PK), 교수번호(FK), 학점
교수 Table = 교수번호(PK), 과목명
BC 정규형으로 만들면 위와 같습니다.
BC 정규형을 만들기 어려운 이유는 주 식별자 속성과 일반 속성인 후보 식별자 간의 관계를 정확히 정의해야 하기 때문입니다.
4 정규형
4 정규형은 다가 종속 개념을 기반으로 하는 정규형입니다.
다가종속은 한 릴레이션에 다가 속성이 두 개 이상 존재할 때 발생할 수 있습니다.
하나의 다가 속성의 모든 값이 다른 다가 속성의 모든 값마다 중복되는 문제점이 발생할 수 있는데 이것이 다가 종속이라 합니다.
다가 종속은 하나의 A 값에 대응하는 여러 개의 B 값이 있고 A 값에 대응하는 여러 개의 C 값이 있고 B 값과 C 값 사이에는 아무런 상관관계가 없는데 A, B, C 값을 하나의 릴레이션에서 관리할 때 발생하는 것입니다.
두 개의 독립적인 일대다(1:M) 관계의 속성이 동일한 릴레이션에 존재하면 다가 종속이 발생합니다.
다가 종속의 모습은 아래와 같습니다
Table 1 = 사원, 기술, 언어
Table 2 = #사원, #기술, #언어
다가 종속이 발생한 릴레이션에서 새로운 엔티티를 생성해 다가 종속을 제거하는 것입니다.
기술과 언어 사이는 직접적인 연관이 없고 단지 한 사원에 속해 있어 간접적인 연관 관계만 존재합니다.
두 개의 릴레이션을 분해해야 합니다.
Table 1 = #사원, #기술
Table 2 = #사원, #언어
5 정규형
5 정규형은 조인 종속 개념을 기반으로 합니다. 조인 종속이 존재하다면 5 정규화 대상이 됩니다.
하나의 릴레이션을 여러 개의 릴레이션으로 분해하여 공통 속성으로 조인하여 데이터 손실 없이 원래의 릴레이션으로 복원할 수 있다면 이것을 무손실 조인이라 합니다.
조인한 결과에 원래 릴레이션에 없는 데이터가 존재하지 않으면 이를 비부가적 조인이라 합니다.
필요한 데이터가 사라지지 않는 무손실 분해가 되고 필요 없는 데이터가 생기지 않는 비부가적 분해가 된 릴레이션이 5 정규형입니다.
하나의 릴레시션을 분해하고 다시 합쳤을 때 원래의 릴레이션으로 복원할 수 있으면 그 릴레이션은 조인 종속이 존재하는 릴레이션입니다. 조인 종속이 존재하지 않을 때까지 분해한 릴레이션이 5 정규형입니다.
Table1 = #사원, #기술, #언어
5 정규형을 위한반 릴레이션 입니다.
Table1 = #사원, #기술
Table2 = #기술, #언어
Table3 = #사원, #언어
세 개의 릴레이션 중 어느 두 개의 릴레이션만 조인해서는 요건을 만족하는 원하는 결과를 얻을 수 없습니다.
반드시 세 개의 릴레이션을 조인해야 원하는 요건을 얻을 수 있습니다.
5 정규형은 조인 종속이 존재하지 않아야 하기 때문에 위와같이 분해하면 5 정규형이 됩니다.
5정규형은 릴레이션을 분할(Project)하고 합치는(join) 개념 때문에 PJ 정규형 이라고도 합니다.
정규화의 성능
정규화를 꺼리는 가장 큰 이유는 성능이 떨어진다는 생각 때문입니다.
잘 구조화된 데이터 모델이 성능 저하를 가져온다는 것은 오류에 가깝습니다.
성능에는 크게 조회 성능과 인서트 성능 두가지 종류입니다. 빠르게 추출해야 하는 조회 성능과 빠르게 저장해야 하는 인서트 성능은 다릅니다.
인서트 성능은 많은 트랜잭션을 최대한 빨리 동시에 입력 처리하는 것을 의밓바니다.
조회 성능에 비해 흔히 발생하지 않지만 핵심 업무와 연결되어 간과하면 큰 문제가 발생할 수 있습니다.
INSERT 구문에 대한 튜닝은 한계가 있으며 방법이 다양하지 않습니다.
한꺼번에 다량이 발생하므로 경합을 줄이는 방향으로 성능 이슈를 해결하는 것이 좋습니다.
그래야 동시에 많은 건수를 저장할 수 있습니다.
조회 성능은 발생 빈도수가 높습니다. 조회 성능도 두 가지로 나눌 수 있습니다.
한 두 건의 소수 데이터를 조회하는 것, 다량의 데이터를 조회하는 것
소수의 데이터를 조회할 때는 성능 문제가 거의 발생하지 않습니다. 하루에 조회하는 횟수가 수십만 건이면 소량의 조회 성능도 시간을 최대한 단축시켜야 합니다. 이럴 때는 1초와 0.9초는 의미 있는 차이일 수 있습니다.
대량의 데이터를 조회하는 요건은 OLTP(Online Transaction Process)에서는 자주 발생하지 않습니다.
소량의 데이터 조회는 주로 인덱스로 해결되며 대량 데이터는 스캔 방법과 조인 방법을 사용해서 해결할 수 있습니다.
또 다른 해결 방법은 비정규형을 채택하는 것입니다.
오라클은 데이터를 블록 단위로 읽습니다. (대부분 DBMS도 비슷)
데이터를 블록 단위로 메모리에 올려 읽는데 해당 데이터가 메모리에 이미 존재하면 바로 메모리에서 빠르게 읽을 수 있습니다.
정규화를 하면 중복 데이터가 최소화되고 인스턴스 크기가 작아집니다. 그럼 한 블록(8Kbytes)에 저장하는 인스턴스는 많아지게 됩니다.
만약 한 블록에 100명의 고객 데이터가 존재하면 특정 고객을 조회할 때 이미 메모리에 올라온 블록에 다른 고객의 데이터도 존재할 수 있어 다른 고객에 대한 조회 성능이 좋아집니다.
연속적인 여러 명의 고객 데이터를 조회할 때 메모리에 존재하는 블록에서 조회할 가능성이 커지게 됩니다.
한 블록에 많은 인스턴스가 존재하면 한 번 메모리에 올라온 블록이 다시 사용될 가능성이 커집니다.
바로 적중률(Hit Rate)이 높아집니다.
그리고 정규화의 기본 개념이 함수 종속이므로 종속성, 의존성이 같은 데이터는 업무에서 같이 조회될 가능성도 높아져 최소의 블록을 사용하는 효과를 얻을 수 있게 됩니다.
같은 성격의 데이터임에도 다른 엔티티에 존재하면 블록도 별도로 존재해 두 개 이상의 블록을 사용해야 합니다.
최소한의 블록을 사용해야 한다는 최종 목표가 있는 조회 성능은 동일한 데이터를 한 블록에 최대한 많이 가질 수 있도록 하는 정규형으로 목표를 달성할 수 있습니다.
최소의 블록을 최대한 자주 사용하도록 하는 것이 조회 성능을 높이는 것으로 정규형은 분명 조회 성능에 도움을 주게 됩니다.
조회 성능일 경우 고려해야 할 중요한 요소 중 하나는 화면의 구성입니다.
화면 구성에 따라 비 정규형을 채택할 수도 있습니다.
데이터 통합 (1) | 2024.02.14 |
---|---|
엔티티 통합 대상 (0) | 2024.02.01 |
모델링 단계 (개념, 논리, 물리) (1) | 2024.01.24 |
데이터 모델링 기본 개념 (1) | 2024.01.23 |
대규모 데이터 부하 분산 위한 계측 방법 (병목 현상, Load Average, vmstat) (1) | 2024.01.14 |
댓글 영역