02_ 반정규화
  & 논리적 데이터 모델링에서 정규화된 엔티티타입, 속성, 관계들을 시스템의 성능과 복잡한 개발 환경을 단순화시키기 위해 반정규화하는 방법을 설명한다.
  & 반정규화란 정규화된 엔티티타입, 속성, 관계를 시스템의 성능 향상, 개발과 운영을 단순화하기 위해 데이터 모델을 통합하는 프로세스를 의미함
  & 데이터의 정합성/무결성 VS 데이터베이스 구성의 단순화/성능
    & 정규화 : 이상적인 경우 엔티티타입, 속성, 관계등은 반드시 한개만 존재, 데이터 값이 이질화 될 수 없음, SQL 작성이 용이하지 않음, 성능 저하 가능성 있음
    & 반정규화 : 여러 테이블을 읽지 않아도 되므로, SQL 작성이 쉽고, 성능이 향상될 가능성 있으나, 데이터가 여러 테이블에 존재 하므로, 데이터 값이 이질화 될 수 있음

#반정규화 주의 사항

& 정확한 데이터의 관리(무결성)가 중요한 관건이며, 정규화가 기본적임
& 하지만 테이블의 복잡성과 성능을 고려하여 View 생성, Partitioning 적용, 인덱스 조정, 클러스터링 적용등의 방안 조사
& 그 다음 반정규화 고려 하며, 반정규화 했을 경우 지속적인 추적 관리 필요

#반정규화 절차

1. 반정규화 대상 조사2. 다른 방법 유도 검토3. 반정규화 대상 조사
{code:noneborderStyle=solid}
- 범위 처리 빈도수 조사
- 대량의 범위 처리 조사
- 통계성 프로세스 조사
- 테이블 조인 개수
{code}
{code:noneborderStyle=solid}
- 뷰(View) 테이블
- 클러스터링 적용
- 인덱스의 조정
- 애플리케이션
{code}
{code:noneborderStyle=solid}
- 테이블 반정규화
- 속성의 반정규화
- 관계의 반정규화
{code}
[그림 7-19] 반정규화 절차
(1) 반정규화의 대상을 조사한다
  • 자주 사용되는 테이블에 접근하는 프로세스 수가 많고, 항상 일정한 범위만을 조회하는 경우
  • 대량의 데이터가 있고, 대량의 범위를 자주 처리하고, 처리 범위를 줄이지 않아 성능을 보장할 수 없는 경우
  • 통계성 프로세스에 통계 정보가 필요할때, 통계 테이블 생성
  • 지나치게 많은 조인이 걸려, 데이터 조회가 기술적으로 어려울 경우
(2) 반정규화의 대상을 다른 방법으로 처리할 수 있는지 검토한다
  • 지나치게 많은 조인 케이스 => 뷰
  • 대량의 데이터 / 대량 범위 처리 => 클러스터링 / 인덱스 조정
  • 대량의 데이터 => 파티셔닝
  • 어플리케이션에서 로직 변경을 통해 성능 향상
(3) 반정규화를 적용한다
  • 반정규화 대상 : 테이블, 속성, 관계
  • 테이블과 속성 관계를 중복으로 가져가는 것 뿐 아니라, 테이블, 속성, 관계를 추가/분할/제거 가능

#반정규화 방법

+테이블 반정규화 방법

1. 테이블 병합2. 테이블 분할3. 테이블 추가
{code:noneborderStyle=solid}
- 1:1 관계의 테이블 병합
- 1:M 관계의 테이블 병합
- 슈퍼타입 서브타입 테이블 병합
{code}
{code:noneborderStyle=solid}
- 수직 분할
- 수평 분할
{code}
{code:noneborderStyle=solid}
- 중복 테이블 추가
- 통계 테이블 추가
- 이력 테이블 추가
- 부분 테이블 추가
{code}
[그림 7-20] 반정규화 방법 - 테이블
(1) 테이블 병합
  • 두 개의 테이블에 발생하는 프로세스가 동일 (항상 SQL 이 두 개의 테이블을 조인하여 작성)
  • 두 테이블을 같이 조회하는 경우가 많고, 관계가 1:1 이면서, 한쪽에서 필수 관계, PK 동일
  • 두 테이블의 관계가 1:M 이라도, 항상 조인해서 사용
  • 슈퍼타입 - 서브타입 관계
(2) 테이블 분할
  • 성능 혹은 전략 적인 측면에서 테이블 분할 할 수 있음
    • [성능] 특정 속성들만 집중적으로 사용
    • [성능] PK에 따라 특별한 범위만 집중적으로 사용
    • [분산] 지역별/서버별 분산 전략
      • 분할 하지 않아도 성능이 저하되지 않는다면, 분할(분산) 안해도 됨
        • 스캔 범위 축소됨
        • 잠금(Lock), 경합(Contention) 감소
        • SQL 문장이 복잡해짐 (UNION ALL 등..)
        • 분할된 모든 테이블 조회시 성능 저하 가능성

① 테이블의 수직적 분할

[그림 7-21] 테이블 분할-수직 분할

& 테이블의 특정 속성들만 집중적으로 사용 (프로세스가 특정 컬럼에 다르게 발생)

[그림 7-22] 이미지 타입을 위한 테이블 분리

& 특별한 데이터 타입 (BLOB, LONG)

② 테이블의 수평적 분할

[그림 7-23] 테이블 분할-수평 분할

& 테이블을 로우(Row) 단위로 나눔
& 테이블에 많은 정보가 있지만, 특정 구간만 선별하여 조회하는 경우
& 위의 예는, 수납 이력 데이터가 월별로 200만건 발생, 프로세스는 월별로 처리하는 경우가 많을 때
& 오라클 에서는 파티셔닝 테이블 기능 활용

(3) 테이블 추가
[그림 7-24] 통계 테이블의 활용

& 통계/이력 관리
& 전체 데이터를 읽어야 하거나, 산출 하려는 내용이 복잡 하다면 원 테이블에서 직접 읽지 말고, 통계 테이블을 분리하여 시스템 사용이 적은 시간에 배치에 의해서 원하는 데이터를 생성한다.

+ 컬럼 반정규화 방법
& 성능 저하 / 접근 경로 복잡한 경우 컬럼의 중복 / 로우의 중복을 통해 해결
& 모델링시 정의된 FK는 관계 역할도 하지만, 부모 테이블의 PK를 복제하여 이용하는 역할도 함
◎ 중복 컬럼 추가
◎ 파생 컬럼 추가(컬럼, 로우에 의한 파생 컬럼)
◎ 이력 테이블 컬럼 추가
◎ PK에 의한 컬럼 추가
◎ 응용 시스템의 오(誤) 작동 처리를 위한 컬럼 추가

(1) 중복 컬럼 방법

& 성능 향상 / 인덱스 사용 고려

(2) 중복 컬럼 특징

& 자주 조인 발생하는 컬럼, 접근 경로가 너무 복잡한 경우 => 읽기 성능 향상, SQL 작성 용이
& 데이터 무결성 확보 어려움, 추가 디스크 공간 필요, 중복된 속성에 대한 소유권 혼동
& 가능하면 한테이블에서 관리 추구 => 뷰/그룹함수 적용 가능성 검토 => 도저히 방법이 없을때 적용

(3) 중복 컬럼 추가

① 해당 테이블에서 자주 사용하는 컬럼인 경우에 컬럼을 중복시킨다

[그림 7-26] 컬럼 중복 - 자주 사용하는 컬럼 중복

& 소스 테이블의 도메인과 일치, 속성명 변경 가능
② 데이터를 조회하는 경로를 단축하기 위해 컬럼을 중복시킨다

[그림 7-27] 컬럼 중복 - 조회 경로 단축

& 비식별자 관계인 경우 관계된 테이블을 모두 조인해야 함 (고객 - 주문 - 주문목록 - 배송)

[그림 7-28] 컬럼 중복 - 조회 경로 단축

& 주식별자 관계인 경우 PK 가 상속이 되므로, 문제 없음

(4) 파생 컬럼추가

① 컬럼에 의한 파생 컬럼 추가

[그림 7-29] 컬럼 추가 - 파생 컬럼

& 조회시 성능 저하 VS 수정시 성능 저하
② 로우에 의한 파생 컬럼 추가

[그림 7-30] 로우에 의한 파생 컬럼 추가

& 특정 로우에 있는 값이 변경되는 경우 전체 로우 값을 다시 계산 해야 하는 단점으로 인해 가급적 피하는것이 좋음, 그룹 함수 추천

(5) 이력 데이터 모델의 컬럼 추가

① 변경 이력, 발생 이력에 대한 최신 정보 컬럼 추가

[그림 7-31] 최신 정보를 나타내는 컬럼 추가

& MAX 등을 사용하여 최신 정보 추출시 성능 저하가 예상됨, 주문목록이력.진행여부 추가로 인해 문제 해소
② 진행 이력에 대한 종료 일자 컬럼 추가

[그림 7-32] 진행 이력
[그림 7-33] 종료를 나타내는 컬럼 추가

& 특정 날짜의 공사진행 상태를 조회시, 인라인뷰를 통하게 되어, 성능 저하가 예상됨, 공사진행.진행상태종료일자 추가로 인해 문제 해소

(6) PK에 의한 컬럼 추가

① 복합 PK에 의한 컬럼 추가

[그림 7-34] 복합 PK
[그림 7-35] 복합 PK - 컬럼 추가

& 복합 PK : 하나의 PK에 여러 개의 의미가 이는 속성을 모아 구성한 키
& 위의 예에서 PK 인덱스 활용 및 인덱스 생성 불가 (FBI 가능)
& 접수.사업소번호 를 추가로 인해 문제 해소
② PK에 의한 컬럼 추가

[그림 7-36] 다중 컬럼으로 구성된 PK

& 인조키, 자식 테이블에서 불필요한 조인이 발생하지 않도록 고려
& 자식 테이블이 없거나, 자식 테이블이 항상 자신 테이블과 같이 움직일 경우

(7) 시스템 오(誤)작동 처리를 위한 컬럼 추가
[그림 7-37] 오입력 처리를 위한 컬럼 추가
[그림 7-38] 오입력 처리를 위한 컬럼 추가

& 이력 관리가 아닌 단순히 사용자의 오입력 처리를 위함
& 처리하지 말아야 하는 경우, 클라이언트에서 처리, 시스템 복잡성 증가, 정합성 위협 을 고려

+ 관계 반정규화 방법

[그림 7-39] 관계 중복-조회 경로 단축

& 고객 - 주문 - 주문목록 - 배송 관계가 있음에도, 경로 단축을 위해 관계 중복 시킴 (고객 - 배송)
& 테이블 관계가 5~6단계 까지 내려가면서, 중간에 비식별자 관계료 연결되어 있고, 빈번하게 조인되는 경우 => 고려