
💡 다중값을 가지는 경우?
- 데이터를 꺼내 쓸 때, 불필요한 split을 사용해야 하는 번거로움이 생길 수 있다.
- 모든 인스턴스가 추가된 속성의 개수만큼 속성값을 가지고 있지 않을 수 있기 때문에 공간의 낭비가 발생할 수 있다.
ex1) 회원 테이블 → 회원, 직업 테이블
회원(회원id, 이름, 생년월일, 직업)
| 회원id(PK) | 이름 | 생년월일 | 직업 |
|---|---|---|---|
| 1 | 홍길동 | 20030303 | 가수, 배우, 작곡가 |
| … | ... | … | … |
회원(회원번호, 이름, 생년월일)
| 회원id(PK) | 이름 | 생년월일 |
|---|---|---|
| 1 | 홍길동 | 20030303 |
| … | … | … |
회원직업정보(회원직업정보id, 회원id, 회원번호 직업)
| 회원직업id(PK) | 회원id(PK) | 직업 |
|---|---|---|
| 1 | 1 | 가수 |
| 2 | 1 | 배우 |
| 3 | 1 | 작곡가 |
ex2) 회원 테이블 → 회원, 사이트 테이블
회원(회원id, 이름, 생년월일, 사이트1, 사이트2, 사이트3)
| 회원id(PK) | 이름 | 생년월일 | 사이트1 | 사이트2 | 사이트3 |
|---|---|---|---|---|---|
| 1 | 홍길동 | 20030303 | 인스타그램 | 구글 | 유튜브 |
| 2 | 김철수 | 20051010 | 인스타그램 | 네이버 | NULL |
회원(회원id, 이름, 생년월일)
| 회원id(PK) | 이름 | 생년월일 |
|---|---|---|
| 1 | 홍길동 | 20030303 |
| 2 | 김철수 | 20051010 |
회원사이트정보(회원사이트정보id, 회원id사이트)
| 회원사이트정보id(PK) | 회원id(FK) | 사이트 |
|---|---|---|
| 1 | 1 | 인스타그램 |
| 2 | 1 | 구글 |
| 3 | 1 | 유튜브 |
| 4 | 2 | 인스타그램 |
| 5 | 2 | 네이버 |
💡 주식별자가 복합식별자인 경우?
- 일반속성이 주식별자의 일부에만 종속될 수 있다.
ex) 일반속성 음료명이 주식별자 중 음료코드에만 종속
주문(주문번호, 음료코드, 음료명, 주문수량, 음료명)
| 주문번호(PK) | 음료코드(PK) | 주문수량 | 음료명 |
|---|---|---|---|
| 20250225001 | A1001 | 2 | 아메리카노 |
| 20250225002 | A1002 | 1 | 아이스티 |
| 20250225003 | A1002 | 1 | 아이스티 |
주문(주문번호, 음료코드, 주문수량)
| 주문번호(PK) | 음료코드(FK) | 주문수량 |
|---|---|---|
| 20250225001 | A1001 | 2 |
| 20250225002 | A1002 | 1 |
| 20250225003 | A1002 | 1 |
음료(음료코드, 음료명)
| 음료코드(PK) | 음료명 |
|---|---|
| A1001 | 아메리카노 |
| A1002 | 아이스티 |
ex) 일반속성인 소속사명이 다른 일반속성인 소속사코드에 종속
참가자(참가번호, 이름, 생년월일, 소속사코드, 소속사명)
| 참가번호(PK) | 이름 | 생년월일 | 소속사코드 | 소속사명 |
|---|---|---|---|---|
| 1 | 홍길동 | 20090305 | A001 | AC엔터테인먼트 |
| 2 | 김철수 | 20101020 | B001 | BD엔터테인먼트 |
| 3 | 최영희 | 20090703 | B001 | BD엔터테인먼트 |
참가자(참가번호, 이름, 생년월일, 소속사코드)
| 참가번호(PK) | 이름 | 생년월일 | 소속사코드(FK) |
|---|---|---|---|
| 1 | 홍길동 | 200090305 | A001 |
| 2 | 김철수 | 20101020 | B001 |
| 3 | 최영희 | 20090703 | B001 |
소속사(소속사코드, 소속사명)
| 소속사코드(PK) | 소속사명 |
|---|---|
| A001 | AC엔터테인먼트 |
| B001 | BD엔터테인먼트 |
A, B → C , C → B R1(A, C), R2(C, B)반정규화 ⭐️⭐️
데이터의 조회 성능을 향상시키기 위해 데이터의 중복을 허용하거나 데이터를 그룹핑하는 것
테이블 반정규화 ⭐️

테이블 병합
1:1 관계 테이블 병합
Ex) 회원 ⊕ 회원상세 → 회원

1:M 관계 테이블 병합
Ex) 주문 ⊕ 주문상세 → 주문

중복된 데이터가 생길 수 있음(주문일자, 회원번호, 결제수단)
1에 해당하는 엔티티의 속성 개수가 많으면 병합했을 때 중복 데이터가 많아지므로 적절하지 않음
슈퍼-서브 타입 테이블 병합
EX) super(사건), sub(일반 사건, 특수 사건 등)
테이블 분할
테이블 수직 분할: 엔티티의 일부 속성을 별도의 엔티티로 분할 (1:1 관계 성립)
자주 사용하는 속성이 아니거나 대부분의 인스턴스가 해당 속성값을 NULL 로 갖고 있을 때 고려
Ex) 회원 → 회원 ⊕ 회원배우자

💡 테이블을 수직 분할하면 한 개의 블록에 더 많은 인스턴스를 저장할 수 있게 된다. ✅
- 디스크 I/O를 줄일 수 있다.
- 데이터베이스는 데이터를 블록 단위로 저장 및 검색한다.
- 이 블록은 크기가 정해져 있기 때문에 한 행의 길이가 길어지면 한 블록에 담을 수 있는 행 개수가 적어진다.
- 그래서 수직 분할하면, 한 블록에 담을 수 있는 행 개수가 많아져서 검색 성능이 좋아질 수 있다.
테이블 수평 분할: 엔티티의 인스턴스를 특정 기준으로 별도의 엔티티로 분할
Ex) 주문 → 주문(2024) ⊕ 주문(2025)
파티션 기능을 사용하여 주문일자에 따라 데이터를 물리적으로 분리

💡 파티셔닝 vs. 샤딩
- 파티셔닝(Partitioning)
- 수평/수직 분할
- 하나의 DB 안에서 분리하여 저장
- 관리 용이성, 쿼리 최적화
- 샤딩(Sharding)
- 수평 분할
- 여러 개의 DB 서버에 분산하여 저장
- 성능 최적화, 확장성
테이블 추가
컬럼 반정규화 ⭐️
관계 반정규화(중복관계 추가) ⭐️