본문 바로가기

Database/MySQL

데이터베이스 반정규화(Denormalization)

1. DB 반정규화란?

  • 성능 향상을 위해 정규화를 포기하는 것.
  • 즉, 성능 향상을 위해서 데이터 중복을 허용하고 조인을 줄이는 용도로 사용한다.
  • 당연한 이야기지만, 모델 간 종속성이 높아지고 확장성이 떨어지지만, 조회 속도를 향상시킬 수 있다.

1) 반정규화 문제점

  • 데이터의 무결성이 항상 보장되지는 않으므로 제한적으로 사용해야한다.

2. 테이블 반정규화

  • 테이블 병합, 분할, 추가로 반정규화를 진행한다.

1) 테이블 병합

  • join을 수행하지 않도록 테이블을 통합하여 성능을 높이는 것을 의미

2) 테이블 분할

(1) vertical partitioning

  • 컬럼 단위로 테이블을 1:1 분리

[1] 수직 분할 예시

id name phone
1 dexter 01022223333
2 bob 01033334444
  • vertical partitioning 적용
id name
1 dexter
2 bob

 

id phone
1 01022223333
2 01033334444

 

[2] vertical partitioning 장점

  • 특정 칼럼들만 CRUD 작업하고 싶을 때, 필요한 부분만 작업할 수 있어서 성능이 향상된다.

[3] vertical partitioning 단점

  • 테이블들에 있는 데이터가 모두 필요한 경우 테이블 간 join 비용이 증가한다.

 

(2) sharding

  • row 단위로 테이블을 분리

[1] sharding하는 이유

  • 하나의 테이블이 너무 많은 데이터를 가지고 있으면 용량 이슈가 생길 수 있다.
  • CRUD 작업이 서비스 성능에 영향을 줄 수 있다.
  • 그래서 DB 트래픽을 분산하기 위해 사용한다.

[2] 어떤 규칙으로 테이블을 자를지 방법

  • Shard key를 어떻게 정의하느냐에 따라 데이터를 효율적으로 분산시키는 것이 결정된다.

첫 번째, Hash sharding

  • 특정 조건에 따라 key값을 정의하는 것을 의미.

- 한 예로,

key 조건 : id % 4 

cluster [node0, node1, node2, node3] 

  • 이렇게 정의하면 id의 나머지에 따라 각각의 노드에 분산되어 저장된다.
  • 단점은 규칙을 바꾸어야 하기 때문에 모든 노드에 데이터가 차면 확장하는데 어려움이 있다.

ps. 

  • cluster란 0,1,2,3 노드들의 집합을 의미
  • 각 node는 table을 의미.

 

두 번째, Dynamic sharding

  • 특정 순서에 따라 key값을 정의하는 것을 의미.
  • 보통 한 테이블에서 id 번호 순서에 따라 각 노드에 데이터를 배정한다.

- 한 예로,

  • 0~30, 31~60, 61~90,,,, 이렇게 배정하는 방식이다.
  • 장점은 나중에 노드를 추가하는데 용이하다.

3) 테이블 추가

(1) 중복테이블 추가

  • 타 서버에 있는 테이블과 동일한 구조의 테이블을 본 서버에 추가
  • 그래서 원격 조인방지

(2) 통계테이블 추가

  • 통계값을 미리 계산해서 저장하는 테이블 추가

order

id account_id order_date product_id
...      

order_statistic

id order_date 일일주문수량 일일주문금액
...      

 

(3) 이력테이블 추가

  • 마스터 테이블에 존재하는 row를 트랜잭션 발생 시점에 따라 복사해두는 테이블 추가

(4) 부분테이블 추가

  • 자주 조회되는 컬럼들만 별도로 모아놓은 테이블 추가

3. 컬럼 반정규화

  • 중복, 파생, 이력테이블 컬럼 추가로 표현한다.

1) 중복컬럼 추가

  • join 프로세스를 줄이기 위해 중복 컬럼 추가
  • SELECT 비용은 감소하지만 UPDATAE 비용은 증가

account

id name

 

order

id account_id

order_product

id order_id

delivery

id order_id order_product_id account_id
  • 배달 테이블이 원래는 회원 id와 연관관계가 존재하지 않는다. order 테이블을 거쳐서 delivery 테이블에 도달해야하므로 join 비용이 증가한다. 검색 효율을 향상시키기 위해 account_id를 delivery 테이블에 추가한다.

2) 파생컬럼 추가

  • 계산을 통해 얻어지는 결과값을 테이블에 컬럼으로 저장

order

id account_id total_price(파생컬럼)

order_product

id order_id order_count

 

product

id order_product price

 

  • product 테이블의 price와 order_product 테이블의 order_count를 곱해서 total_price로 order 테이블에 저장

3) 이력테이블 컬럼 추가

  • 이력 테이블에 기능성 컬럼 추가(최신 여부, 시작일 or 종료일 등)

product

id price

 

product_price_log(이력테이블)

id product_id update_date old_price recent_price

 

4. 관계 반정규화

  • 중복관계 추가

1) 중복관계 추가

  • 데이터 처리를 위해 여러 경로를 거쳐야 할 경우 관계를 중복시킴으로써 성능 개선
  • 한 예로, "회원 - 주문 - 주문상품 - 배송", 이러한 관계가 있다고 가정할 시,  회원 - 배송까지 가려면 4개의 테이블을 조인해야한다. 그래서 배송에 회원 id 연관관계를 넣어서 join 비용을 줄인다.
  • 자세한 예는 중복컬럼 추가를 참고하길 바란다.

 

 

 

 

reference

https://www.youtube.com/watch?v=SS6H2whbfwc