개발공부/SQL

[SQL] 정규화(Normalization)

jnnjnn 2024. 4. 29. 21:46

 

정규화란?


데이터베이스 정규화는 데이터베이스 내의 구조를 조직화하고 최적화하는 과정입니다

 

정규화를 하는 이유

  • 데이터의 중복을 줄이고 데이터의 무결성을 보장한다
  • 데이터 효율을 높인다
  • 이상 현상을 방지한다

일반적으로 제1~3정규화를 진행합니다

 

이상현상

데이터 정규화를 하지 않은 데이터베이스는 다음과 같은 이상현상이 발생할 수 있습니다

👉 고객 정보와 주문 정보를 같은 레코드에 저장하는 데이터베이스를 예로 들면,

  • 삽입 이상(Insertion Anomaly) : 새로운 데이터를 삽입할 때 원하지 않는 문제가 발생합니다
    👉 새로운 고객을 등록하려 할 때, 주문 정보가 없어 삽입이 불가능 할 수 있다

  • 삽입삭제 이상(Delete Anomaly) : 특정 데이터 삭제 시, 다른 데이터도 함께 손실되는 현상이 발생합니다
    👉 고객의 정보를 삭제하면 그 고객에 대한 모든 주문 정보도 함께 삭제될 수 있다

  • 갱신 이상(Update Anomaly) : 속상값 갱신 시 일부 값만 갱신되어 모순이 발생합니다
    👉 한 고객이 주문을 여러 개 하고, 배송 주소를 변경할 때, 모든 주문의 배송 주소를 변경해주어야 함
    따라서 데이터의 일관성을 유지하기가 어렵다

 

 

 

정규화의 종류


 

제1정규화(1NF)

1) 각 행을 유일하게 구분하는 컬럼이 존재합니다 -> Primary Key가 존재

2) 모든 데이터는 원자적으로 저장됩니다 -> 한 컬럼에 여러 값이 저장되지 않는다

 

Primary Key

1. NOT NULL이면서 UNIQUE 한 값이어야 한다

2. 바뀔 가능성이 현저히 낮아야 한다

3. 가장 좋은 PK는 의미없는 칼럼이다

 

강의 학생
국어 이상혁
수학 최우제, 이민형
영어 문현준, 류민석

 

위의 데이터에서 학생은 여러 개의 값을 가지고 있어 데이터를 원자적으로 저장한다는 조건을 만족하지 못한다.

번호 강의 학생
1 국어 이상혁
2 수학 최우제
3 수학 최우제
4 영어 문현준
5 영어 류민석

 

다음과 같이 수정하고 기본키(Primary Key)인 번호를 추가해주었다

 

CREATE TABLE lecture
(
    id         INT PRIMARY KEY AUTO_INCREMENT,
    subject VARCHAR(10),
    student VARCHAR(10)
);

 

제2정규화(2NF)

1) 제1정규화를 만족한다

2) 기본키의 부분집합이 결정자가 되어서는 안된다

학생이름 강좌이름 강의실 성적
안진아 JAVA 501 B
강동현 JAVA 501 A
박재형 DB 502 A
김예빈 Python 503 A+

 

이 테이블에서 기본키는 학생이름+강좌이름으로 복합키이다. 그리고 학생이름과 강좌이름에 의해서 성적이 결정된다.

그런데 강의실은 기본키의 부분집합인 강좌이름에 따라 결정되고 있으므로 2번 조건을 만족하지 않는다.

 

따라서 다음과 같이 수정할 수 있다

 

학생이름 강좌이름 성적
안진아 JAVA B
강동현 JAVA A
박재형 DB A
김예빈 Python A+

 

강좌이름 강의실
JAVA 501
DB 502
Python 503

 

CREATE TABLE Students
(
	student_name VARCHAR(10),
	lecture_name VARCHAR(10),
    grade VARCHAR(3)
    PRIMARY KEY (student_name, lecture_name)
    FOREIGN KEY (lecture_name) REFERENCES Classroom (lecture_name)
);

CREATE TABLE Classroom
(
	lecture_name VARCHAR(10),
    room_number VARCHAR(10)
);

 

제3정규화(3NF)

1) 제2정규화를 만족한다

2) 이행적 종속을 없애야 한다

 

이행적 종속이란?

A->B, B->C가 성립할 때, A -> C가 성립하는 것을 말한다

고객이름 고객등급 혜택
이상혁 1 무료배송
최우제 2 할인
문현준 3 라운지
이민형 2 할인

 

위의 테이블은 고객이름이 고객등급을 결정하고, 고객등급이 해당 등급에 따른 혜택을 결정하고 있다.

이는 이행적 종속을 삭제하는 조건 2를 만족하지 않기에 다음과 같이 수정할 수 있다

 

고객이름 고객등급
이상혁 1
최우제 2
문현준 3
이민형 2

 

고객등급 혜택
1 무료배송
2 할인
3 라운지

 

CREATE TABLE Customer
(
    id         INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(3),
    level      INT,
    FOREIGN KEY (level) REFERENCES Customer_benefit (level)
);

CREATE TABLE Customer_benefit
(
    level   INT PRIMARY KEY,
    benefit VARCHAR(100)
);