We.TIL 37 : 정규화(Normalization)

김기욱·2020년 9월 17일
1

We.TIL

목록 보기
58/69

정규화란

다양한 유형의 검사를 통해 데이터모델을 더욱 명확하게 구조화하고 개선시켜나가는 절차

정규화의 목적

  1. 불필요한 데이터를 제거해서 데이터 중복의 최소화
  2. 데이터베이스 구조 확장 시 리모델링을 최소화
  3. 다양한 관점에서 쿼리실행
  4. 데이터무결성의 시행을 간단하게 만듬
  5. 각종 이상현상(Anomaly)의 방지

정규화의 대상

이커머스에서 상품 관리, 주식 거래 시스템 같이 CRUD가 많이 발생하는 데이터베이스는 데이터의 정합성과 무결성이 매우 중요하므로 정규화가 필요하다.

반대로 분석리포트같이 데이터베이스에서 다수의 조회가 필요하고 join과 caculation이 많이 발생시키는 작업을 수행할 때는 연산속도가 중요하므로, 연산속도 향상을 위해 부분적으로 반정규화(denormalization)을 한다.

정규화의 과정

주문ID주문일회원ID회원명회원등급상품ID상품명주문량단가구매금액
12020-09-10Kim김준우수A01도마1개20,00020,000
12020-09-10Kim김준우수B01주방칼3개10,00030,000
12020-09-10Kim김준우수C01접시4개5,00020,000
22020-09-11Lee이수일반A01도마2개20,00040,000
32020-09-14Park박경일반C01접시1개5,0005,000
32020-09-14Park박경일반D01행주3개2,0006,000
42020-09-18Choi최은우수B01주방칼2개10,00020,000

[그림1] 주문테이블

제 1 정규화 : 복수의 속성값을 갖는 속성을 분리

'그림1'에서와 같이 동일한 성격과 내용의 컬럼이 연속적으로 나타나고 있을 때, 해당 컬럼을 제거하고 기본 테이블의 PK를 추가해 새로운 테이블을 생성하고, 기존의 테이블과 One to many의 관계를 형성한다.

'그림1'에서는 (같은 주문일임에도)하나의 주문에 여러 상품이 있을 때 주문정보가 계속 중복되기 때문에 주문테이블과 주문상세 테이블로 분리한다.

<주문테이블>

주문ID(PK)주문일회원ID회원명회원등급
12020-09-10Kim김준우수
22020-09-11Lee이수일반
32020-09-14Park박경일반
42020-09-18Choi최은우수

<주문상세테이블>

상품ID(PK)주문ID(PK/FK)상품명주문량단가최종금액
A011도마1개20,00020,000
A012도마2개20,00040,000
B011주방칼3개10,00030,000
B014주방칼2개10,00020,000
C011접시4개5,00020,000
C013접시1개5,0005,000
D013행주3개2,0006,000

제 2 정규화 : PK가 여러키로 구성된 복합키로 구성된 경우, 복합키 일부분에만 종속되는 속성들을 분리(부분적 함수 종속관계 분리)

주문상세테이블에서 자신의 복합 키 중 '상품ID'에는 의존하지 않기 때문에 이를 상품 테이블로 따로 분리한다.

<주문테이블>

주문ID(PK)주문일회원ID회원명회원등급
12020-09-10Kim김준우수
22020-09-11Lee이수일반
32020-09-14Park박경일반
42020-09-18Choi최은우수

<주문상세테이블>

주문ID(PK/FK)상품ID(PK/FK)주문량최종금액
1A011개20,000
1B013개30,000
1C014개20,000
2A012개40,000
3C011개5,000
3D013개6,000
4B012개20,000

<상품테이블>

상품ID(PK)상품명단가
A01도마20,000
B01주방칼10,000
C01접시5,000
D01행주2,000

제 3 정규화 : 테이블 키가 아닌 컬럼들은 PK에 의존해야 하는데 겉으로 그런것 처럼 보이지만 실제로 기본키가 아닌 일반 컬럼에 의존하는 컬럼들이 있을 수 있다. 이를 이전적 함수 종속 관계라고 한다. 3정규화에서는 PK에 의존하지 않고 일반컬럼에 의존하는 컬럼들을 분리한다.

회원명과 회원등급이 주문ID가 아닌 일반컬럼인 회원ID에 의존하고 있다. 그러므로 분리한다.

<회원테이블>

회원ID(PK)회원명회원등급
Kim김준우수
Lee이수일반
Park박경일반
Choi최은우수

<주문테이블>

주문ID(PK)주문일회원ID(FK)
12020-09-10Kim
22020-09-11Lee
32020-09-14Park
42020-09-18Choi

<주문상세테이블>

주문ID(PK/FK)상품ID(PK/FK)주문량최종금액
1A011개20,000
1B013개30,000
1C014개20,000
2A012개40,000
3C011개5,000
3D013개6,000
4B012개20,000

<상품테이블>

상품ID(PK)상품명단가
A01도마20,000
B01주방칼10,000
C01접시5,000
D01행주2,000

예제는 가독성을 위해 상품아이디와 회원아이디 형태를 string으로 구현했지만
실제로는 테이블이 형성될 때 테이블마다 PK용 ID값을 따로 INT로 부여하는것이 좋다. 그래야만 PK값이 중복되지 않고, 1개로 유지되기 때문이다.

참조 : https://wkdtjsgur100.github.io/database-normalization/

https://dog-foot-story.tistory.com/61

profile
어려운 것은 없다, 다만 아직 익숙치않을뿐이다.

0개의 댓글