관계형 데이터 모델링 노트 : 07 비정규화 이야기
Chapter 7 : 비정규화 이야기
서론
- “관계형 데이터 모델링 노트” 책을 통해 진행한 이론 스터디 일곱번째 시간이다.
비정규화에 대해서는 엄청나게 많은 이야기들이 있다. 그만큼 논란이 많은 주제라서 그런거 같다. 그래도 내가 공부한 책을 기준으로 작성하니 “관계형 데이터 모델링 노트” 에서는 이렇게 이야기 하는구나 라고 생각하고 포스팅을 보면 좋겠다.
비정규화에 대한 서설
-
비정규형 모델은 단순히 정규화를 하지 않은 모델이 아니라, 정규화를 마친 후에 비정규화를 한 모델이다.
-
비정규화는 조회 성능을 향상시키기 위해서 데이터를 중복하거나 그룹핑하는 과정을 의미한다.
-
비정규화는 크게 두 가지 방법으로 나타난다. 하나는 정규화를 거꾸로 적용한 것으로써 역정규화라는 용어가 어울리는 방법이다. 다른 하나는 정규형 모델에 중복 속성을 채택하는 것으로써 대부분 비정규화를 이 방법을 수행한다.
-
[그림 7.1]은 정규형 모델이다. 주문의 기본 데이터를 관리하는 주문 엔티티와 주문 상품을 관리하는 주문 상품 엔티티는 마스터, 상세 관계 이면서, 일대다 관계의 모델이다.
- [그림 7.2] 모델은 위의 정규형 모델을 역으로 비정규화(역정규화)한 모델이다.
- [그림 7.2] 모델은 [그림 7.1] 주문 엔티티를 주문상품 엔티티에 합쳐서 비정규화를 수행한 모델이다. 반면에 실무에서는 대부분 [7.3]과 같은 모델이 사용된다. 즉 정규형을 모델을 그대로 사용하면서 필요한 속성(배송주소)만 중복 시키는 것이다.
비정규화 원칙
-
최우선적으로 고려할 요소는 데이터 무결성(Integrity)이다.
-
정규형은 필수이며, 성능 문제가 있을 때만 비정규형을 채택한다.
-
중복 속성을 가능한 사용하지 않으며, 추출 속성은 일부 사용할 수 있다.
비정규형의 단점
- 비정규형의 장점은 조회 성능 향상 하나 밖에 없는 반면에 단점은 많다.
1) 정합성
- 비정규형의 가장 커다란 단점은 데이터 정합성이 깨질 수 있다는 것이다.
2) 쓰기 성능 저하
- 비정규화를 사용하는 이유는 읽기 성능을 향상시키기 위해서이다. 이와 다르게 쓰기 성능은 떨어지기 때문에 쓰기 성능이 문제가 될 수 있다.
3) 데이터 성격이 불명확
- 비정규화를 하면 데이터 성격이 불명확해진다. 중복 속성이 많아지면 본래 엔티티의 성격이 희석될 수 있다. 예를 들면 속성만 봐도 엔티티가 어떤 성격인지 알 수 있어야 되는데 중복 속성이 많으면 속성만 보고는 엔티티의 성격을 파악하기 힘들다.
4) 모델 확장성 저하
- 모델의 확장성 측면에서도 비정규형 모델이 정규형 모델보다 불리하다.
5) 개발 어려움
- 비정규형을 채택하면 개발이 편리할 거 같지만, 데이터 정합성을 맞추기 위해서 발생하는 노력이 더 크다.
6) 공간 차지
- 중복 데이터를 많이 사용하면 데이터베이스의 저장 공간을 더 많이 차지하게 된다.
7) 일부 조회 성능 저하
- 경우에 따라서는 비정규화로 인해 조회 성능이 떨어질 수 있다.
비정규화 과정
- 좋은 비정규형 모델이 되려면 다음과 같은 과정을 거쳐야 된다.
1) 함수 종속을 적용해 정규화
2) 성능 문제 발생 요건 도출
3) 비정규 외에 다른 방안 검토
- 뷰를 사용해서 조인 문제를 해결할 수 있는지 검토
- 파티션으로 데이터를 나눠서 해결할 수 있는지 검토
- 클러스터링이나 IOT같은 특수 형태의 테이블을 사용해서 해결할 수 있는지 검토
- 인덱스를 조정하거나 힌트 등으로 해결할 수 있는지 검토
- 그 밖에 DBMS의 최신 기술을 적용해 해결할 수 있는지 검토
4) 비정규화 수행
5) 정합성 구현 방안 검토
비정규화 방법 - 역정규화
-
역정규화는 비정규화 보다는 협소한 의미다. 비정규화의 일부가 역정규화다. 아래 모델처럼 정규화 모델을 역으로 되돌려서 역정규화된 모델을 만드는 것이 역정규화이다.
-
아래 모델의 경우 일반적인 정규화된 모델이다.
-
위의 모델을 역정규화를 하면 아래와 같은 모델이된다. 이러한 모델은 유연하지 않아 확장성이 떨어진다.
비정규화 방법 - 엔티티 합체
-
논리 모델링 단계에서 데이터 정체성(성격)을 파악해 엔티티를 도출하면 엔티티가 많이 생긴다. 자연히 엔티티 간의 조인이 많이 발생해 성능 문제를 발생할 수 있어 엔티티를 합체할 필요가 있다.
-
엔티티 합체는 두 개 이상의 엔티트를 합치는 것이다. 엔티티 합체 대상에서는 일대일 관계의 엔티티가 주를 이루며, 간혹 일대다 관계의 엔티티도 대상이 된다.
-
일대일 관계의 엔티티를 합체한느 것은 엄밀히 비정규화는 아니지만 넓은 의미에서는 비정규화로 볼 수 있다.
-
아래와 같이 일대다 관계의 엔티티도 합칠 수 있다. 하지만 많은 중복 데이터가 발생하기 때문에 주의해야 한다. 엄청난 성능 이슈가 없는 한 일대다 엔티티를 합체하는 것은 지양해야 한다.
-
일대다 관계의 엔티티는 보통 하위 엔티티를 기준으로 상위 엔티티를 합친다. 또한 약 결합 관계일 때 보다 강 결합 관계일 때 엔티티를 합체하기 적절하다.
-
엔티티 합체는 엔티티 통합과 다르다 엔티티 합체는 조회 성능을 높이기 위한 비정규화의 한 종류이지만, 엔티티 통합은 모델의 확장성을 위해 엔티티를 일반화하는 것이다.
비정규화 방법 - 엔티티 분해
- 엔티티 분해하는 것은 수직 분해와 수평 분해롤 나눌 수 있다. 수직 분해는 엔티티의 일부 속성을 별도의 엔티티로 분해하는 것이며, 수평 분해는 엔티티의 특정 인스턴스를 별도의 엔티티로 분해하는 것이다. 수평 분해는 주로 파티셔닝으로 구현한다.
1) 엔티티 수직 분해
-
엔티티 수직 분해는 속성의 사용 빈도를 기준으로 하거나 Varchar2(1000), LOB 등과 같은 특별한 데이터 타입을 기준으로 분해한다. 또한 널이 발생할 수 있는 속성을 기준으로 분해하기도 한다.
-
하나의 엔티티를 일대일 관계로 분해하는 근본적인 이유는 한 개의 데이터 블록에 중요한 인스턴스를 많이 저장할 수 있기 때문이다. 또한 로우 체이닝이나 로우 마이그레이션도 감소해 성능에 좋은 영향을 미친다.
2) 엔티티 수평 분해
- 엔티티를 수평으로 분해하는 방법에는 크게 두 가지가 존재한다. 한 가지 방법은 데이터베이스 기능인 파티션을 사용하는 것이고, 또 다른 방법은 특정 기준에 따라 엔티티 인스턴스를 분리해서 다른 엔티티로 이동시키는 것이다. 이 방법은 물리적으로 분리해서 관리하는 것이다.
비정규화 방법 - 요약 엔티티
-
요약 엔티티는 원천 데이터를 대상으로 합계나 집계 등 미리 계산한 데이터를 저장한 엔티티다. 다른 비정규화 방법과 마찬가지로 조회 성능을 극적으로 향상시킬 수 있다.
-
요약 데이터는 광범위하게 사용되는데 유/불리를 판단하기가 쉽지 않다. 모든 요약 엔티티를 중복 데이터라고 판단하는 것도 바람직하지 않다.
-
미리 계산해 놓은 것도 데이터를 중복해서 관리하는 방법이어서 데이터 정합성을 주의해야한다. 원천 데이터를 사용해서 계산한 것이므로 원천 데이터가 수정되면 요약 엔티티도 어떤 식으로든 처리돼야 한다. 원천 데이터 당 하나의 집계 엔티티만 사용하는 것이 바람직하다.
-
원천 데이터의 수정에 따른 정합성을 맞추는 방법도 두 가지가 있다. 원천 데이터가 수정되는 시점에 실시간으로 요약 엔티티를 수정하는 방법과 특정 시간을 정해 배치로 요약 엔티티의 데이터를 맞추는 방법이 있다.
비정규화 방법 - 추출 속성
-
추출 속성은 기존에 존재하는 속성의 값을 추출하여 저장한 속성을 말한다. 기존 속성의 값을 더한 값, 카운트한 값, 최근 값, 이전 값, 최대 값, 최소 값 등을 관리하는 속성이 추출 속성이다.
-
기존 값을 그대로 복사해서 사용하는 속성도 추출 속성에 속한다.
-
추출 속성을 사용하는 목적은 미리 추출(계산)해서 보관한 값을 필요한 시점에 사용하기 위해서다. 필요한 때마다 계산하지 않기 위함이다. 연산할 대상의 범위가 넓거나 연산이 복잡할 때 미리 계산해서 저장해 놓고 조회할 대마다 사용하면 효과적일 수 있다.
-
추출 속성은 주로 하위 엔티티에서 많은 데이터(인스턴스)를 읽어서 연산한 후의 값을 상위 엔티티의 속성으로 가져다 놓는다. 따라서 주로 상위 엔티티의 속성 값을 하위 엔티티에 가져다 놓는 중복 속성과 달리 추출 속성은 성능에 많은 영향을 미친다.
-
추출 속성에서 중에는 관계속성도 존재한다. 여러 단계를 거쳐 상위 엔티티를 조인하면 성능이 저하될 수 있으므로 해당 엔티티와 직접 관계를 관리한다.
이전 값을 관리하는 모델을 설계하는 방법
-
데이터를 이력 관리할 때, 이전 값을 관리하는 방법은 몇가지가 있다. 이전 값을 조회하는 요건의 중요도에 따라 적절한 방법을 사용해야 한다. 아래는 일반적인 이력 데이터를 관리하는 모델이다.
-
또한 아래와 같이 현재 고객명을 관리하기 위해서 중복 속성을 사용할 수 있다.
비정규화 방법 - 추출 엔티티
- 추출 속성을 사용하는 방법과 유사한 방법이 추출 엔티티를 사용하는 것이다. 추출 엔티티는 추출 속성을 묶어서 사용하는 개념이다.
비정규화 방법 - 반복 속성
-
반복 속성을 사용한 엔티티는 1 정규형을 위반한 엔티티다. 따라서 정규화를 검토하는 것이 우선이지만 비정규화를 할 때도 있다.
-
반복 속성을 사용하는 가장 중요한 판단 기준은 반복 개수가 고정돼 있는지다. 그리고 조회 조건이 [1-ROW] (횡) 형태로 나오는지 확인해야 한다. [n-ROW] 형태라면 정규화를 하는 것이 좋다.
-
반복 속성을 사용한 비정규형에는 두 가지 종류가 있다. 롤업 역정규화가 있고 단순한 비정규화가 있다.
비정규화 방법 - 중복 데이터
-
중복 데이터를 사용하는 방법은 크게 두가지다. 엔티티를 복사한 후 데이터까지 복해서 중복 데이터를 사용할 수 있으며, 모델 구조에는 변함 없이 중복 데이터를 사용할 수 있다. 전자는 다양한 방법으로 많이 사용하고 있는 방법이다. 후자는 모델 구조는 달라지는 것이 없지만, 데이터를 중복해서 사용하기 때문에 넓은 의미에서 비정규화에 포함한다.
-
서버가 다를 때 원격 조인을 피할려고 엔티티를 그대로 복제하여 중복 관리할 수 도 있다.
끝마치며
- 비정규화 이야기를 끝으로 “관계형 데이터 모델링 노트” 에 대한 이야기는 끝이 났다. 이번 시리즈는 첫번째 엔티티 이야기에서 얘기했던거 처럼 이론 스터디에서 공부한 내용을 기반으로 작성하였다. 많은 시간을 할애했지만 생각보다 깔끔하게 정리 못한것이 아쉽지만, 그래도 이렇게 끝마칠 수 있어서 뿌듯한 시간이었다.
이전에 스터디를 같이 진행한 멘토님께서 이 책은 여러번 읽어봐야 된다고 했지만 나는 아직 4회독 정도 밖에 하지 못했다. 나중에 기회가 된다면 다른 스터디 모임을 통해서 다시 공부할 수 있는 시간을 가지면 좋을거 같다. 다음 시간에는 더 좋은 주제로 더 나은 글 재주를 가지고 돌아오도록 하겠습니다. 이 글을 읽어 주신 분들께 감사 인사드리며 이번 포스팅을 마무리하겠습니다!
댓글남기기