해당 포스트는
SQLD
를 학습하며 정리한 내용에 대한 포스트입니다.
이론을 학습한 내용을 정리하고 퀴즈, 기출문제 등을 기록하려고 합니다.
🌈 정규화 (Normalization)
데이터 정합성(데이터의 정확성과 일관성을 유지하고 보장)을 위해 엔터티를 작은 단위로 분리하는 과정
테이블 간의 중복된 데이터를 허용하지 않겠다.
*무결성을 유지
, DB의 저장용량 감소
정규화는 데이터의 일관성
, 최소한의 데이터 중복
, 최대한의 데이터 유연성
을 위한 방법이며 데이터를 분해하는 과정이다
정규화는 데이터 중복을 제거하고 데이터 모델의 독립성
을 확보하기 위한 방법
정규화를 수행하면 비지니스에 변화가 발생해도 데이터 모델의 변경을 최소화
할 수 있다.
정규화는 제 1정규화부터 제 5정규화까지 있지만, 실직적으로 제 3정규화 까지만 수행한다.
정규화를 할 경우 데이터 조회성능은 처리조건에 따라 향상되는 경우도 있고 저하되는 경우도 있다.
입력, 수정, 삭제 성능은 일반적으로 향상
엔터티의 의미해석이 명확해진다.
정규화를 수행하면 일반적으로 테이블 수가 증가한다.
정규화는 모델의 독립성을 향상시킨다.
정규화의 단점
정규화는 장점만 있을까?
정규화를 하면 엔터티가 계속 증가하게 된다.
엔터티의 수가 증가하면 JOIN으로 인한 조회 성능 저하가 발생할 수 있다.
이상현상
이 테이블은 정규화를 수행하지 않은것으로, 부서 테이블과 직원 테이블을 하나로 합쳐둔 것이다.
만약 좌측의 테이블에서 새로운 직원이 추가되는 경우 부서 정보가 없으면 부서코드를 임의의 값으로 넣어야 한다.
즉, 불필요한 정보가 같이 추가되는 것이다. 또한 새로운 “총무부”가 추가되어야 할 경우 사원 정보가 없기 때문에 임의의 값으로 사원 번호를 입력하거나 추가할 수 없게 된다.
이러한 문제를 이상현상(Anomaly)이라고 한다.
- 삽입이상 : 기본적으로 주문되지 않은 상품의 정보를 삽입할 수 없으며, 강제로 삽입하기 위해서는 존재하지 않는 가짜 주문번호를 만들어주어야함.
- 갱신이상 : 중복된 데이터 중 일부만 업데이트되어 데이터의 불일치가 발생하게 되는 현상
- 삭제이상 : 데이터 삭제 시 삭제되면 안되는 데이터까지 덩달아 삭제되는 현상
이상현상 해결을 위한 테이블 분해
앞서 보았던 사진의 이상현상 같은 문제를 해결하기 위해서는 테이블을 분해해야 한다.
정규화된 모델은 테이블이 분해된다.
테이블이 분해되면 직원 테이블과 부서 테이블 간에 부서코드로 조인(JOIN)을 수행하여 하나의 합집합으로 만들 수도 있다.
정규화를 수행하면 불필요한 데이터를 입력하지 않아도 되기 때문에 중복 데이터가 제거된다.
정규화 절차 | 설명 |
---|---|
제1정규화(1NF) | - 속성(Attribute)의 원자성 을 확보한다. - 기본키(Primary)를 설정 한다. |
제2정규화(2NF) | - 기본키가 2개 이상의 속성 으로 이루어진 경우 부분 함수 종속성을 제거 분해 한다. |
제3정규화(3NF) | - 기본키를 제외한 컬럼 간에 종속성을 제거 한다. 즉, 이행 함수 종속성을 제거한다. |
BCNF | - 기본키를 제외하고 후보키 가 있는 경우, 후보키가 기본키를 종속시키면 분해 한다. |
제4정규화(4NF) | - 여러 컬럼들이 하나의 컬럼을 종속시키는 경우 분해하여 다중값 종속성을 제거 한다. |
제5정규화(5NF) | - 조인에 의해서 종속성이 발생 되는 경우 분해한다. |
💻 제1정규화 (1NF)
제1정규화의 목표
모든 속성은 반드시 하나의 값만 가져야 한다.
테이블의 컬럼이
원자값(Atomic Value)을 갖도록 테이블을 분해
정규화는 함수적 종속성을 근거로 한다.
함수적 종속성이란 X➡Y 이면 Y는 X에 함수적으로 종속된다고 한다.
이런 경우는 회원ID가 기본키가 되고, 회원ID가 이름을 함수적으로 종속한다고 한다.
위의 예를 보면 계좌 테이블 X가 Y의 컬럼들을 함수적으로 족속하고 있다.
X는 계좌번호 하나만으로는
유일성
을 만족하지 못한다고 가정한 것이다.그래서 계좌번호와 회원ID를 기본키로 설정한 것.
이처럼 기본키를 잡는 것과 원자성을 가지는 것이 바로 제1정규화이다.
- 모든 속성은 반드시
하나의 값
만 가져야 한다.
이름 | 생년월일 | 직업 |
---|---|---|
이꼬비 | 900402 | 개발자,연구원,유튜버 |
이름 | 직업 |
---|---|
이꼬비 | 개발자 |
이꼬비 | 연구원 |
이꼬비 | 유튜버 |
유사한 속성이 반복되는 경우도 1차 정규화의 대상이 된다.
중복속성에 대한 분리가 1차 정규화의 대상이 되며, 로우 단위의 중보도 1차 정규화의 대상이 되지만 컬럼 단위로 중복되는 경우도 1차 정규화의 대상이다.
PK에 대해 반복되는 그룹(Repeating)이 존재하지 않아도 1차 정규형이라고 할 수 있다.
이름 | 생년월일 | 사이트1 | 사이트2 | 사이트3 |
---|---|---|---|---|
이꼬비 | 900402 | 인스타그램 | 페이스북 | 유튜브 |
김서방 | 981231 | 인스타그램 | 트위터 | NULL |
이름 | 사이트 |
---|---|
이꼬비 | 인스타그램 |
이꼬비 | 페이스북 |
이꼬비 | 유튜브 |
김서방 | 인스타그램 |
김서방 | 트위터 |
위와 같은 엔터티가 존재하는 경우 왜 문제가 되는걸까?
하나의 속성이 다중값을 가지는 경우 어플리케이션에서 데이터를 꺼내 쓸 때
불필요한 Split을 사용
해야 한다.한 엔터티 내에 유사한 속성이 반복되는 경우 데이터가 늘어날 때 계속해서 속성을 추가해야하고 반대로 모든 인스턴스가 추가된 속성의 개수만큼 속성값을 가지고 있지 않을 수 있으므로
공간의 낭비가 발생
할 수 있다.
💻 제2정규화 (2NF)
제2정규화의 목표
엔터티의 모든 일반속성은 반드시 모든 주식별자에 종속되어야 한다.
부분 함수 종속성이 발생하면 분해
기본키가 2개 이상의 컬럼
으로 이루어진 경우에만 발생한다.
부분 함수 종속성이란?
기본키를 제외하고 컬럼 간에 종속성이 발생하는 것
위의 예는
기본키가 2개이기 때문에 제2정규화 대상
이다.기본키에 있는 회원ID가 변경되면 이름이 변경된다.
회원ID가 이름을 함수적으로 종속하고 있는 것이다.
바로 이러한 경우를 부분 함수 종속성이라고 한다.
부분 함수 종속성이 발생하면 분해해야 한다.
부분 함수 종송성을 제거하면 위와 같다.
회원이라는 새로운 테이블이 도출되고 회원ID가 기본키가 된다.
엔터티의 모든 일반속성은 반드시 모든 주식별자에 종속
되어야 한다.
주식별자가 단일식별자가 아닌 복합식별자인 경우 일반속성이 주식별자의 일부에만 종속될 수 있다.
제2정규화
제2정규화는
제1정규화 수행 이후
에 하는 것으로기본키가 2개 이상
의 속성으로 이루어진 관계에서만 제2정규화를 수행하고 하나의 속성으로 이루어져있다면 제2정규화는 생략가능하다.
💻 제3정규화(3NF)
제3정규화의 목표
주식별자가 아닌 모든 속성 간에는 서로 종속될 수 없다. (이행함수종속성 : 속성 간 종속성을 가지면 안된다.)
이행함수 종속성이 발생하면 분해
이행 함수종속성이란?
기본키를 제외하고
컬럼 간에 종속성이 발생하는 것
주식별자를 제외한 컬럼 간에 종속성
을 확인해서 종속성이 있을 경우 분할하는 과정이므로주식별자와의 관련성이 낮음
제3정규화는
제1정규화와 제2정규화를 수행한 다음
에 해야 한다.
위처럼 관리점이 관리점 코드에 종속 되는 것을 이행 함수 종속성이라 한다.
제3정규화를 수행하면 위처럼 관리점 테이블이 도출되고 관리점 코드가 기본키가 된다.
💻 BCNF (Boyce-Codd Normal Form)
제3정규화보다 좀 더 강한 것
BCNF는
복수의 후보키
가 있고, 후보키들이복합 속성
이어야 하며,서로 중첩
되어야 한다.
위의 예처럼 기본키(학번, 과목번호)가 교수를 함수적으로 종속하고 있다.
이 때 교수가 후보키(최소성과 유일성을 만족)이고 교수가 과목 번호를 함수적으로 종속하는 경우 분해가 일어난다.
즉, 위와 같은 경우 교수 테이블을 새롭게 만들고 기본키는 교수로 하고 컬럼은 과목번호가 된다.
이러한 작업을 BCNF라고 한다.
BCNF
- 복수의 후보키가 존재
- 후보키들이 복합 속성
- 서로 중첩되어 있어야 함.
후보키가 기본키의 속성 중 하나를 함수적으로 종속할 때
테이블 분해를 하는 정규화 과정이다.
💻 정규화 예제
정규화 대상 테이블
제품번호 | 제품명 | 재고수량 | 주문번호 | 수출 여부 | 고객 번호 | 사업자 번호 | 우선순위 | 주문 수량 |
---|---|---|---|---|---|---|---|---|
1001 | 모니터 | 1990 | AB345 | x | 4520 | 398201 | 1 | 150 |
1001 | 모니터 | 1990 | AD347 | y | 2341 | - | 3 | 600 |
1007 | 마우스 | 9702 | CA210 | x | 3280 | 200212 | 8 | 1200 |
1007 | 마우스 | 9702 | AB345 | x | 4520 | 398201 | 1 | 300 |
1007 | 마우스 | 9702 | CB230 | x | 2341 | 563892 | 3 | 390 |
1201 | 스피커 | 2108 | CB231 | y | 8320 | - | 2 | 80 |
✍ 제1정규화
속성을 보고 한 개의 속성을 유일성을 만족할 수 있는지 확인
제품번호는 1001, 1007 등이 두번 이상 나오므로 중복되고, 주문번호 또한 AB345가 두 번 나와서 중복된다.
결과적으로 한 개의 속성으로는 유일성을 만족할 수 없다.
- 그러므로 2개의 조합으로 유일성을 만족할 수 있는지를 확인해 보아야 한다.
제품번호 + 주문번호가 식별자가 되면 엔터티의 유일성을 만족하게 된다.
제1정규화는 이러한 식별자를 찾는 과정이며 여기까지 수행하면 된다.
제1정규화 결과
제품번호 | 제품명 | 재고수량 | 주문번호 | 수출 여부 | 고객 번호 | 사업자 번호 | 우선순위 | 주문 수량 |
---|---|---|---|---|---|---|---|---|
1001 | 모니터 | 1990 | AB345 | x | 4520 | 398201 | 1 | 150 |
1001 | 모니터 | 1990 | AD347 | y | 2341 | - | 3 | 600 |
1007 | 마우스 | 9702 | CA210 | x | 3280 | 200212 | 8 | 1200 |
1007 | 마우스 | 9702 | AB345 | x | 4520 | 398201 | 1 | 300 |
1007 | 마우스 | 9702 | CB230 | x | 2341 | 563892 | 3 | 390 |
1201 | 스피커 | 2108 | CB231 | y | 8320 | - | 2 | 80 |
✍ 제2정규화
제2정규화는
기본키가 두 개 이상인 경우
대상이 된다.기본키가 제품번호 + 주문번호이므로 제2정규화 대상이다.
제2정규화는 모든 속성(제품명, 재고 수량, 수출 여부 등)이 식별자에 종속해야 하며 그렇지 않은 경우에는 분해한다.
확인 방법은 제1정규화와 마찬가지로 중복을 확인하는 것이다.
제2정규화 확인(1)
제품번호 | 제품명 | 재고수량 |
---|---|---|
1001 | 모니터 | 1990 |
1001 | 모니터 | 1990 |
위의 경우를 보면 1001, 모니터가 중복되는 것을 확인할 수 있다.
이러한 경우에 엔터티를 분해하는 것이 제2정규화이다.
제2정규화 확인(2)
주문번호 | 수출 여부 | 고객 번호 | 사업자 번호 | 우선순위 |
---|---|---|---|---|
AB345 | x | 4520 | 398201 | 1 |
AD347 | y | 2341 | - | 3 |
CA210 | x | 3280 | 200212 | 8 |
AB345 | x | 4520 | 398201 | 1 |
위의 경우도 AB345 주문번호에 중복이 발생한다.
이러한 경우는 분해를 해야 한다.
결과적으로 최종 엔터티는 다음과 같다.
제2정규화 결과
엔터티명: 제품
제품번호 | 제품명 | 재고 수량 |
엔터티명: 주문_고객
주문번호 | 수출 여부 | 고객 번호 | 사업자 번호 | 우선순위 |
엔터티명: 주문
제품번호 | 주문번호 | 주문 수량 |
- 위와 같이 3개의 엔터티가 도출된다.
💻 정규화와 성능
🚨 정규화의 문제점
정규화는 테이블을 분해해서 데이터 중복을 제거하기 때문에
데이터 모델의 유연성을 높인다
.정규화는 데이터 조회(SELECT) 시에 조인(Join)을 유발하기 때문에 CPU와 메모리를 많이 사용한다.
적절한 정규화는 성능상 이롭지만 지나친 정규화는 오히려 성능 저하를 일으킬 수 있다.
🚨 정규화의 문제점 예제 1
앞에서의 테이블은 직원과 부서 테이블에서 부서 코드가 같은 것을 찾는 것이다. 이것을 프로그램화한다면 중첩된 루프(Nested Loop)를 사용해야 한다.
1
2
3
for(i = 0; i < N; i++)
for(j= 0; j < M; j++)
if(직원_부서코드[i] == 부서_부서코드[j]{ }
위의 예에서 N은 직원 테이블의 건수이고 M은 부서 테이블의 건수이다.
결과적으로 이중으로 for문을 사용해서 비교하는 기능을 만들어야 조인을 할 수 있다.
이러한 구조는 데이터양이 증가하면 비교해야 하는 건수도 증가한다.
물론 실제로 위와 같은 비효율이 발생하지는 않는다.
이러한 문제를 해결하기 위해서 인덱스와 옵티마이저(Optimizer)가 있는 것이다.
결론적으로 조인이 부하를 유발하는 것은 분명하다.
정규화의 문제점을 해결하기 위해서 반정규화를 하여 하나의 테이블에 저장한다면 조인을 통한 성능 저하는 해결될 것이다.
이런 성능 저하를 해결하기 위해 반정규화가 있는 것이다.
옵티마이저(Optimizer)란? 🎯
옵티마이저는 가장 효율적인 방법으로 SQL을 수행할 최적의 처리 경로를 생성해주는 DBMS의 핵심 엔진이다.
컴퓨터의 두뇌가 CPU인 것처럼 DBMS의 두뇌는 옵티마이저라고 할 수 있다.
인덱스(INDEX)란? 🎯
인덱스는 RDBMS에서 검색 속도를 높이기 위한 기술이다.
TABLE의 컬럼을 색인화(따로 파일로 저장)하여 검색 시 해당 TABLE의 레코드를 Full Scan하는 것이 아니라 색인화 되어있는 인덱스 파일을 검색하여 검색 속도를 빠르게 한다.
🔧 정규화를 사용한 성능 튜닝
조인으로 인하여 성능이 저하되는 문제를 반정규화로 해결할 수 있다.
반정규화는 데이터를 중복시키기 때문에 또 다른 문제점을 발생시킨다.
위의 예처럼 계좌 마스터의 컬럼이 계속적으로 증가하면 조인이 최소화되기 때문에 조회를 빠르게 할 수 있을 것이다.
하지만 너무 많은 컬럼이 추가되면 한 개 행의 크기가 데이터베이스 관리 시스템의 입출력 단위인 블록의 크기(Block Size)를 넘어서게 된다.
그렇게 되면 한 개의 행을 읽기 위해서 여러 개의 블록을 읽어야 한다.
한 행을 읽기 위해서 여러개의 블록을 읽게 되면 디스크 입출력이 증가하기 때문에 성능이 떨어지게 된다.
반정규화는 이러한 문제점을 유발할 수 있다.
위와 같은 문제가 발생하면 테이블을 분해하는 방법밖에 없다.
따라서 정규화는 입출력 데이터의 양을 줄여서 성능을 향상시킬 수 있는 것이다.
🚨 정규화의 문제점 예제 2
회원의 배송상태를 조회하려면 여러 번의 JOIN을 해야 함
위와 같은 경우 회원의 배송상태를 조회하기 위해서는 여러번의 JOIN이 불가피
이럴 때는 오히려 반정규화를 통해 성능을 개선해야함
어떤 측면의 성능을 우선으로 할 것이냐의 딜레마
회원 엔터티와 배송 엔터티 간의 관계를 생성하여 성능 개선
🎯 추가 내용
성능 데이터 모델링
데이터베이스의 성능을 향상시키기 위해 설계 단계부터 성능과 관련된 사항들이 모델링에 반영될 수 있다.
분석/설계 단계에서 데이터베이스 처리 성능을 향상 시킬 수 있는 방법을 고려해야 한다.
데이터의 증가가 빠를수록 성능저하에 따른 성능개선비용 증가
데이터 모델은 성능을 튜닝하면서 변경이 될 수 있다.
분석/설계 단계에서 성능을 고려한 데이터모델링을 수행할 경우 성능 저하에 따른 Rework 비용을 최소화할 수 있는 기회를 가지게 된다.
성능 모델링의 방법으로는 정규화, 반정규화, 테이블 통합, 테이블 분할 등이 있다.
성능 데이터 모델링의 순서
- 데이터 모델에 맞게 정규화를 수행
- 데이터베이스의 용량 및 트랜젝션 유형을 파악, 성능저하 유무 검토
- 용량과 트랜잭션 유형에 맞게 반정규화 수행
- 성능 향상을 위한 이력모델의 조정, PK/FK 조정, 슈퍼/서브타입 조정 등을 수행
- 데이터 모델의 성능을 검증
📚 레퍼런스
정미나. (유튜브 선생님에게 배우는) 유선배 SQL개발자(SQLD) 과외노트 / [정미나 저] (2023). Print.
한국데이터산업진흥원. SQL 자격검정 실전문제 : 국가공인 SQL전문가·국가공인 SQL개발자 / 한국데이터산업진흥원 [편] (2020). Print.