메인 콘텐츠로 건너뛰기

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
데이터베이스 정규화는 중복을 줄이고 갱신 이상을 막기 위해 테이블을 구성하는 과정입니다. 대부분의 애플리케이션은 제3 정규형(3NF)에 도달해야 합니다. 그 너머에서는 이득은 대부분 이론적이고 조인 복잡성은 실재합니다.

제1 정규형(1NF)

모든 열이 원자 값(셀당 하나의 값)을 담고 반복 그룹이 없을 때 테이블은 1NF입니다. 1NF 위반 — 여러 값이 한 열에 묶여 있음:
1NF 충족 — 셀당 하나의 값, 반복 그룹은 자식 테이블로 추출:

제2 정규형(2NF)

1NF이면서 모든 비키 열이 기본 키의 일부가 아니라 전체에 종속될 때 테이블은 2NF입니다. 이는 복합 기본 키를 가진 테이블에만 적용됩니다. 2NF 위반 — product_name이 전체 (order_id, product_id) 키가 아니라 product_id에만 종속됨:
2NF 충족 — product_name을 자체 테이블로 옮김:

제3 정규형(3NF)

2NF이면서 어떤 비키 열도 다른 비키 열에 종속되지 않을 때 테이블은 3NF입니다. 이런 종속을 이행적 종속이라고 합니다. 3NF 위반 — city와 state가 customer_id에 직접이 아니라 zip_code에 종속됨:
3NF 충족 — 이행적 종속을 추출:
실제로는 우편번호를 별도 테이블로 추출하는 것은 대부분의 애플리케이션에 과합니다. 모든 엣지 케이스에서의 기계적인 준수보다 원칙이 더 중요합니다.

비정규화해야 할 때

정규화는 쓰기 무결성을 높이고 중복을 줄이지만, 읽기에 조인 오버헤드를 더합니다. 읽기 중심이나 분석 워크로드에서는 때때로 의도적인 비정규화가 타당합니다. 비정규화하기 전에 인덱스를 확인하세요. 느린 조인 문제의 대부분은 인덱스 누락 문제입니다. 조인 열에 커버링 인덱스를 추가하는 것으로 충분한 경우가 많습니다. MySQL 인덱스의 동작 방식을 참고하세요. 비정규화는 애플리케이션이 데이터를 쓰는 바로 그 테이블이 아니라 읽기 복제본이나 OLAP 저장소에서 가장 잘 동작합니다.

자주 묻는 질문

3NF 너머까지 가야 하나요?

대부분의 애플리케이션에는 3NF로 충분합니다. 보이스-코드 정규형(BCNF)은 겹치는 후보 키가 3NF에서도 여전히 이상을 허용하는 엣지 케이스를 다루는데, 학술적 연습 밖에서는 거의 생기지 않는 상황입니다. 제거하려는 특정 이상이 있는 것이 아니라면 3NF에서 멈추세요.

성능을 위해 비정규화해야 하나요?

구조를 바꾸기 전에 프로파일링하세요. 대부분의 느린 쿼리는 조인이 아니라 인덱스 누락 때문입니다. 먼저 인덱스를 추가하세요. 인덱스가 잘 걸린 쿼리가 큰 테이블에서 여전히 느리다면, 트랜잭션 데이터베이스가 아니라 읽기 복제본이나 구체화된 요약 테이블에서의 비정규화를 고려하세요.

2NF 위반과 3NF 위반의 차이는 무엇인가요?

2NF 위반은 기본 키의 일부에 종속되는 열입니다(복합 PK에서만 가능). 3NF 위반은 다른 비키 열에 종속되는 열입니다. 2NF는 부분 키 종속에 관한 것이고, 3NF는 비키 열을 거치는 이행적 종속에 관한 것입니다.

문제 해결

함께 보기