현재 선택한 SQL 과정

SQLD 이론 학습

이론 목록으로 돌아가기

반정규화: 성능을 위한 의도적 중복

정규화된 모델을 출발점으로 반정규화의 적용 조건·기법·무결성 비용을 판단한다.

예상 읽기 6

핵심 요약

정규화된 모델을 출발점으로 반정규화의 적용 조건·기법·무결성 비용을 판단한다.

핵심 질문

  1. 반정규화: 성능을 위한 의도적 중복를 실제 업무 사례에서 어떤 기준으로 판별하는가?
  2. 한 행이 나타내는 업무 사실과 유일성·필수성·변경 가능성은 무엇인가?
  3. 잘못 모델링하면 어떤 중복·이상 현상·변경 영향이 발생하는가?
  4. 여러 설계안 중 업무 의미와 변경 용이성을 가장 잘 보존하는 안을 어떻게 고르는가?

학습 목표

  • 반정규화가 정규화의 반대 작업만을 뜻하지 않는 이유를 설명한다.
  • 테이블·컬럼·관계 수준의 반정규화 기법을 사례에 적용한다.

개념 지도

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
후보키·함수 종속성 → 이상 현상 → 정규형 분해 → 성능 측정 → 제한적 반정규화

핵심 내용

반정규화는 조회 성능이나 운영 단순화를 위해 의도적으로 중복을 허용하거나 구조를 조정하는 설계다. 먼저 정규화된 모델과 실제 SQL, 데이터량, 변경 빈도를 확인한 뒤 적용한다.

  • 테이블: 병합, 분할, 요약·집계 테이블 추가
  • 컬럼: 중복 컬럼, 파생 컬럼, 이전·현재 상태값 저장
  • 관계: 잦은 조인을 줄이기 위한 중복 관계 추가

예를 들어 주문 목록에서 고객명을 매우 자주 조회한다고 주문에 고객명을 복제하면 조인은 줄지만, 고객명 변경 시 모든 주문의 값을 맞춰야 한다. 따라서 갱신 주체, 동기화 방식, 검증 절차가 설계에 포함되어야 한다.

적용 순서

  1. 병목 SQL과 업무 요구를 측정한다.
  2. 인덱스·SQL 개선·캐시 등 다른 방법을 검토한다.
  3. 읽기 이득과 쓰기·무결성 비용을 비교한다.
  4. 적용 후 성능과 불일치를 감시한다.

흔한 오해와 주의점

  • 반정규화는 데이터 무결성을 포기하는 작업이 아니다.
  • 정규화가 항상 느리고 반정규화가 항상 빠른 것은 아니다.
  • 컬럼 중복은 저장 공간뿐 아니라 변경 경로와 잠금 범위도 늘릴 수 있다.

문항 풀이 보강: 반정규화 기법 선택

반정규화는 단순히 테이블을 합치는 작업이 아니다.

수준대표 기법주된 이득함께 드는 비용
테이블병합, 수직·수평 분할, 통계·이력·요약 테이블조인·스캔 범위 감소동기화·추가 저장
컬럼중복 컬럼, 파생 컬럼, PK 컬럼의 일반 컬럼 복제반복 조인·계산 감소갱신 경로 증가
관계중복 관계 추가긴 조인 경로 단축참조 무결성 관리

자주 사용하는 소수 컬럼과 거의 사용하지 않는 큰 컬럼이 한 넓은 테이블에 섞여 블록당 행 수가 줄어든다면, 1:1 수직 분할로 핵심 컬럼을 별도 테이블에 둘 수 있다. 행의 종류나 기간별로 읽는 범위가 명확하면 수평 분할을 검토한다.

주문목록을 조회할 때 매번 제품 테이블과 조인하는 비용이 실제 병목이라면 제품명을 주문목록에 중복할 수 있지만, 제품명 변경 시 과거 주문의 이름을 바꿀지 보존할지 업무 규칙부터 정해야 한다.

적용 전 체크

  1. 정규화를 정확히 수행한다.
  2. 데이터 용량과 증가량을 산정한다.
  3. 트랜잭션 유형·빈도·범위를 파악한다.
  4. 병목 SQL을 측정한다.
  5. 인덱스나 SQL 개선으로 해결 가능한지 본다.
  6. 읽기 이득이 쓰기·무결성 비용보다 클 때만 적용한다.

정규화 → 용량 산정 → 트랜잭션 분석 → 반정규화·PK/FK·인덱스 검토의 흐름을 기억한다.

중복 컬럼의 Source of Truth 설계

주문에 고객명을 복제한다고 가정한다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
CUSTOMER.customer_name  현재 고객명 원천
ORDERS.customer_name    주문 당시 이름 Snapshot 또는 현재 이름 Cache

두 컬럼의 의미를 먼저 정해야 한다. 과거 주문서에 주문 당시 이름을 남기는 것이라면 값이 달라도 오류가 아니다. 현재 고객명을 빠르게 보여 주기 위한 Cache라면 고객명 변경 시 동기화가 필요하다.

동기화 방식 비교

방식장점위험
동일 Transaction에서 함께 갱신즉시 일관성여러 Table Lock·업무 결합 증가
Trigger누락 방지숨은 부하·재귀·오류 추적 어려움
Event/비동기 갱신쓰기 응답 분리일시적 불일치·재처리 필요
Batch 재생성단순·대량 효율최신성 지연
Materialized ViewQuery Rewrite·관리 기능Refresh 비용·제약

반정규화된 값마다 원천, 갱신 주체, 허용 지연, 검증 Query, 재생성 절차를 문서화한다.

적용 전후 검증

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
-- 중복값 불일치 점검 예
SELECT COUNT(*)
FROM   orders o
JOIN   customer c ON c.customer_id = o.customer_id
WHERE  o.cached_customer_name <> c.customer_name
   OR (o.cached_customer_name IS NULL AND c.customer_name IS NOT NULL)
   OR (o.cached_customer_name IS NOT NULL AND c.customer_name IS NULL);

읽기 SQL의 Join·Buffers가 실제로 줄었는지와 DML 시간·Redo·Lock이 얼마나 늘었는지를 함께 측정한다. 측정 근거와 복구 경로가 없다면 정규화 구조를 유지한다.


사례를 판별하는 순서

  1. 모델이 표현해야 하는 업무 사실과 행 단위(Grain)를 한 문장으로 정의합니다.
  2. 각 인스턴스를 유일하게 식별할 수 있는 후보와 변경 가능성을 확인합니다.
  3. 속성이 어느 사실에 종속되는지와 관계의 필수성·카디널리티를 확인합니다.
  4. 중복 저장으로 삽입·갱신·삭제 이상이 생기는지 검토합니다.
  5. 물리 성능을 이유로 구조를 바꿀 때 원천 데이터와 동기화·복구 규칙을 함께 설계합니다.

모델 품질 확인표

  • 같은 업무 사실이 여러 곳에 중복 저장되지 않는가?
  • 이름과 도메인이 한 가지 의미로 사용되는가?
  • PK·FK가 실제 업무 관계와 선택성을 정확히 표현하는가?
  • 현재 화면이나 프로세스에 과도하게 종속되지 않는가?
  • 정규화와 성능 설계의 이유를 측정 가능한 근거로 설명할 수 있는가?

마지막 점검

  • 화면의 입력 항목이나 현재 프로세스를 그대로 엔터티·관계로 옮기지 않습니다.
  • 한 행의 업무 사실, 후보 식별자와 함수 종속성을 먼저 확정합니다.
  • 중복과 비일관성을 만들면서 조회 편의만 얻는 설계를 정답으로 선택하지 않습니다.
  • 반정규화와 물리 설계는 측정된 성능 문제와 동기화·복구 대책이 있을 때 적용합니다.

복습 문제

  1. 파생 금액을 저장하기 전에 정해야 할 세 가지는?
  2. 반정규화 판단보다 먼저 확보해야 할 근거는 무엇인가?
  3. 이 개념을 실제 업무 사례에서 판별할 수 있는가?
  4. 한 행의 업무 의미와 식별자를 설명할 수 있는가?