Contents
see List데이터베이스 정규화와 반정규화 전략
정규화는 데이터 중복을 제거하고 무결성을 보장하는 설계 기법이고, 반정규화는 성능을 위해 의도적으로 중복을 허용하는 기법입니다. 상황에 맞는 적절한 균형이 중요합니다.
언제 사용하나요?
- 정규화: OLTP 시스템, 데이터 무결성 중요, 쓰기 빈번
- 반정규화: OLAP/분석, 읽기 성능 중요, 복잡한 조인 제거
정규화 단계
제1정규형 (1NF): 원자값만 저장
- 하나의 컬럼에 여러 값 금지
- 반복 그룹 제거
-- 위반 (전화번호가 여러 개)
| 이름 | 전화번호 |
| 홍길동 | 010-1234, 010-5678 |
-- 1NF 적용
| 이름 | 전화번호 |
| 홍길동 | 010-1234 |
| 홍길동 | 010-5678 |
제2정규형 (2NF): 부분 함수 종속 제거
- 기본키 전체에 종속되어야 함
-- 위반 (수강 테이블, 교수명은 과목에만 종속)
| 학번 | 과목코드 | 교수명 | 성적 |
| 001 | CS101 | 김교수 | A |
-- 2NF 적용 (테이블 분리)
[수강] 학번, 과목코드, 성적
[과목] 과목코드, 교수명
제3정규형 (3NF): 이행적 함수 종속 제거
- 비키 컬럼이 다른 비키 컬럼에 종속 안됨
-- 위반 (부서명은 부서코드에 종속)
| 사원번호 | 부서코드 | 부서명 |
| E001 | D01 | 개발팀 |
-- 3NF 적용
[사원] 사원번호, 부서코드
[부서] 부서코드, 부서명
BCNF: 모든 결정자가 후보키반정규화 기법
1. 테이블 병합
-- 1:1 관계 테이블 합치기
-- 정규화: 회원, 회원상세 분리
-- 반정규화: 회원 테이블에 상세 정보 포함
2. 컬럼 중복
-- 조인 제거를 위해 다른 테이블 컬럼 복사
CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT,
user_name VARCHAR(50), -- users.name 복사
product_id INT,
product_name VARCHAR(100), -- products.name 복사
...
);
3. 파생 컬럼 추가
-- 계산 결과 미리 저장
CREATE TABLE orders (
...
order_total DECIMAL(10,2), -- SUM(item.price * qty) 결과
item_count INT -- COUNT(*) 결과
);
4. 테이블 분할
-- 수평 분할: 행 기준 (파티셔닝)
-- 수직 분할: 컬럼 기준 (자주 쓰는 것 분리)
5. 집계 테이블
-- 통계용 요약 테이블
CREATE TABLE daily_sales_summary (
sale_date DATE PRIMARY KEY,
total_orders INT,
total_amount DECIMAL(15,2),
avg_order_value DECIMAL(10,2)
);실전 예시: 게시판
-- 정규화된 설계
CREATE TABLE posts (
post_id INT PRIMARY KEY,
user_id INT REFERENCES users(user_id),
title VARCHAR(200),
content TEXT,
created_at TIMESTAMP
);
CREATE TABLE comments (
comment_id INT PRIMARY KEY,
post_id INT REFERENCES posts(post_id),
user_id INT REFERENCES users(user_id),
content TEXT
);
-- 반정규화 적용
CREATE TABLE posts (
post_id INT PRIMARY KEY,
user_id INT,
user_name VARCHAR(50), -- 중복: 조인 제거
title VARCHAR(200),
content TEXT,
comment_count INT DEFAULT 0, -- 파생: COUNT 제거
view_count INT DEFAULT 0,
created_at TIMESTAMP
);
-- 댓글 추가 시 트리거로 comment_count 갱신
CREATE TRIGGER update_comment_count
AFTER INSERT ON comments
FOR EACH ROW
BEGIN
UPDATE posts
SET comment_count = comment_count + 1
WHERE post_id = NEW.post_id;
END;반정규화 시 고려사항
1. 데이터 동기화
-- 중복 데이터 일관성 유지 방법
-- 트리거, 배치 작업, 애플리케이션 로직
2. 저장 공간
-- 중복으로 인한 용량 증가
-- SSD 비용 vs 조인 비용 비교
3. 쓰기 성능
-- 중복 컬럼 갱신 부담
-- 읽기/쓰기 비율 고려
4. 유지보수
-- 데이터 불일치 위험
-- 문서화 필수선택 가이드
| 상황 | 권장 |
|---|---|
| OLTP (트랜잭션) | 정규화 우선 |
| OLAP (분석/리포트) | 반정규화/스타 스키마 |
| 읽기 90% 이상 | 반정규화 고려 |
| 복잡한 조인 (5개+) | 반정규화 고려 |
| 데이터 무결성 중요 | 정규화 유지 |
| 실시간 집계 | 집계 테이블 추가 |
모범 사례
- 먼저 정규화 후, 필요시 반정규화
- 반정규화 결정은 성능 테스트 기반
- 인덱스로 해결 가능한지 먼저 검토
- 캐시(Redis)로 대체 가능한지 검토
- 반정규화 시 문서화 필수