297. 스노우플레이크 스키마

핵심 인사이트 (3줄 요약)

  1. 본질: 스노우플레이크 스키마(Snowflake Schema)는 스타 스키마의 차원 테이블을 3NF(제3정규형)까지 정규화하여 계층적 구조로 만든 차원 모델링 기법이다.
  2. 가치: 데이터 중복 제거, 저장 공간 절약, 데이터 일관성 향상, 단점으로는 조인 증가로 인한 查询 성능 저하가 있다.
  3. 융합: 정규화, 팩트 테이블, 차원 테이블, 조인 성능, OLAP, 스타 스키마, Slowly Changing Dimension과 밀접하게 연관된다.

Ⅰ. 개요 및 필요성 (Context & Necessity)

개념 정의

스노우플레이크 스키마(Snowflake Schema)는 Ralph Kimball의 차원 모델링에서 파생된 변형으로, 스타 스키마에서 차원 테이블을 정규화(제2정규형 이상)하여 계층적 구조로 만든 형태이다. 정규화를 통해 차원 테이블 간의 중복 속성(예: 카테고리명, 브랜드명)을 별도 테이블로 분리하여 관리함으로써, 데이터 중복을 최소화하고 저장 공간을 절약한다. 구조가 눈송이(Snowflake)처럼 다단계로 펼쳐져 보이는 것이 특징이다.

필요성

스타 스키마의 차원 테이블은 비정규화되어 있어 데이터 중복이 발생한다. 예를 들어, 상품 차원 테이블에서 "전자기기" 카테고리가 1000개 상품에 모두 반복 저장된다. 이러한 중복은 저장 공간을 낭비할 뿐만 아니라,某一商品의 카테고리명을 修改해야 할 때 여러 행을 모두 更新해야 하는 관리상의 문제를 야기한다. 스노우플레이크 스키마는 정규화를 통해 이러한 중복을 제거하고, 데이터 무결성과 일관성을 향상시킨다.

배경

스노우플레이크 스키마는 Kimball의 차원 모델링 방법론에서 파생된 것으로, 스타 스키마의 단순성과 조회 성능优位를 유지하면서도 정규화를 통한 데이터 관리를 개선하려는 시도에서 비롯되었다. 그러나 정규화에 따른 조인 증가로 查询 성능이 저하되는 단점이 있어, 실무에서는 차원 테이블의 크기가 매우 크거나 관리가 복잡한 경우에 한해서만 부분적으로采用하는 경우가 많다. 실제로 Kimball 자신도 "스노우플레이크는 일반적으로 피해야 한다"고 조언한 바 있다.

비유

스노우플레이크 스키마는도서관의目次に 비유할 수 있다. 전체 도서 목록(스타 스키마의 차원 테이블)에는 각 책의 저자, 출판사, 장르가 모두 반복 기재되어 있다. 반면 도서관的专业目次に서는 저자를 저자 목次に, 출판사를 출판사 目次に 분리하고, 도서 목록에서는これらの 키(Key)만 참조한다. 이렇게 하면 정보가 한 곳에만 저장되어 관리하기는 쉬워지지만(중복 제거), 특정 도서의 저자명을 찾으려면 도서 목록에서 저자 키를 찾고, 저자 목록에서 실제 이름을 찾아야 하는 번거로움(조인 증가)이 발생한다.

📢 섹션 요약: 스노우플레이크 스키마는 차원 테이블을 정규화하여 데이터 중복을 제거하고 일관성을 향상시키지만, 조인 증가로 인해 查询 성능이 저하되는 트레이드오프가 있다.


Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)

스노우플레이크 스키마 구조

┌─────────────────────────────────────────────────────────────────────────────┐
│                    스노우플레이크 스키마 구조                                   │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  [전체 구조]                                                               │
│  ─────────                                                               │
│                                                                             │
│            ┌─────────────────┐                                             │
│            │   dim_category  │ ← 정규화된 카테고리 테이블 (3NF)             │
│            │─────────────────│                                             │
│            │ category_key PK │                                             │
│            │ category_name   │                                             │
│            │ department      │                                             │
│            └────────┬────────┘                                             │
│                     │                                                        │
│                     │ FK                                                     │
│                     ▼                                                        │
│            ┌─────────────────┐                                             │
│            │dim_sub_category │ ← 정규화된 서브카테고리 테이블                │
│            │─────────────────│                                             │
│            │ sub_cat_key PK  │                                             │
│            │ sub_category    │                                             │
│            │ category_key FK │                                             │
│            └────────┬────────┘                                             │
│                     │                                                        │
│                     │ FK                                                     │
│                     ▼                                                        │
│       ┌─────────────┴─────────────┐                                        │
│       │                           │                                         │
│       ▼                           ▼                                         │
│  ┌─────────────────┐       ┌─────────────────┐                             │
│  │  dim_product    │       │  dim_time       │                             │
│  │─────────────────│       │─────────────────│                             │
│  │ product_key PK  │       │ time_key PK     │                             │
│  │ product_name    │       │ date           │                             │
│  │ sub_cat_key FK  │       │ month          │                             │
│  │ brand_key FK    │       │ quarter        │                             │
│  │ price           │       │ year           │                             │
│  └────────┬────────┘       └─────────────────┘                             │
│           │                                                                │
│           │ FK                                                              │
│           ▼                                                                │
│  ┌─────────────────┐                                                       │
│  │  dim_brand      │ ← 정규화된 브랜드 테이블                                  │
│  │─────────────────│                                                       │
│  │ brand_key PK    │                                                       │
│  │ brand_name      │                                                       │
│  │ manufacturer    │                                                       │
│  └────────┬────────┘                                                       │
│           │                                                                │
│           │                                                                │
│           ▼                                                                │
│  ┌─────────────────────────────────────┐                                   │
│  │           fact_sales               │                                   │
│  │          (팩트 테이블)              │                                   │
│  │─────────────────────────────────────│                                   │
│  │ sales_id PK                         │                                   │
│  │ time_key FK ───────────────────────┘                                   │
│  │ product_key FK                      │                                   │
│  │ customer_key FK                     │                                   │
│  │ store_key FK                        │                                   │
│  │ sales_amt (측정값)                   │                                   │
│  │ sales_qty (측정값)                   │                                   │
│  │ profit_amt (측정값)                  │                                   │
│  └─────────────────────────────────────┘                                   │
│                                                                             │
│  ※ "눈송이" 모양: 차원 테이블이 다단계 정규화 계층 형성                       │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

스타 스키마 vs 스노우플레이크 스키마 비교

┌─────────────────────────────────────────────────────────────────────────────┐
│                    스타 스키마 vs 스노우플레이크 스키마 상세 비교                   │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌──────────────────┬────────────────────────┬────────────────────────┐     │
│  │      특성         │     스타 스키마         │   스노우플레이크 스키마   │     │
│  ├──────────────────┼────────────────────────┼────────────────────────┤     │
│  │ 차원 테이블       │ 비정규화 (1NF)          │ 정규화 (2NF~3NF)        │     │
│  │                  │ (단일 테이블)            │ (다중 테이블 계층)       │     │
│  ├──────────────────┼────────────────────────┼────────────────────────┤     │
│  │ 데이터 중복      │ 높음                    │ 낮음                    │     │
│  ├──────────────────┼────────────────────────┼────────────────────────┤     │
│  │ 저장 공간        │ 더 필요                  │ 절약 가능               │     │
│  ├──────────────────┼────────────────────────┼────────────────────────┤     │
│  │ 조인 경로        │ 팩트-차원 1단계          │ 팩트-차원-서브차원 N단계 │     │
│  ├──────────────────┼────────────────────────┼────────────────────────┤     │
│  │ 조회 성능        │ 빠름                    │ 상대적으로 느림          │     │
│  ├──────────────────┼────────────────────────┼────────────────────────┤     │
│  │ 데이터 일관성    │ 갱신 시 다중 행 update   │ 단일 행 update          │     │
│  ├──────────────────┼────────────────────────┼────────────────────────┤     │
│  │ 관리 용이성      │ 높음 (단순 구조)        │ 낮음 (복잡한 구조)      │     │
│  ├──────────────────┼────────────────────────┼────────────────────────┤     │
│  │ 인덱스 전략      │ 단순                    │ 차원 계층별 인덱스 필요  │     │
│  ├──────────────────┼────────────────────────┼────────────────────────┤     │
│  │ 적합场景        │ 대부분의 DW (70~80%)    │ 차원이 매우 큰 경우,    │     │
│  │                  │ 빠른 응답 우선          │ 관리가 중요한 경우      │     │
│  └──────────────────┴────────────────────────┴────────────────────────┘     │
│                                                                             │
│  [예시: 브랜드명 변경 시]                                                  │
│  ────────────────────────                                                  │
│                                                                             │
│  스타 스키마에서:                                                          │
│  UPDATE dim_product SET brand_name = 'Samsung'                             │
│  WHERE brand_name = '삼성';                                                 │
│  → 여러 행이 影响받을 수 있음 (중복된 brand_name 값들)                        │
│                                                                             │
│  스노우플레이크에서:                                                       │
│  UPDATE dim_brand SET brand_name = 'Samsung'                                │
│  WHERE brand_name = '삼성';                                                 │
│  → 단일 행만 影响받음 (중복 없음)                                           │
│  → 모든 상품에 即時 반영 (foreign key로 참조)                               │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

스노우플레이크 적용 판단 기준

┌─────────────────────────────────────────────────────────────────────────────┐
│                    스노우플레이크 적용 판단 기준                               │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  [스노우플레이크 고려 상황]                                                 │
│  ───────────────────                                                        │
│                                                                             │
│  ✅ 차원 테이블가 매우 큰 경우 (수백만~수천만 행)                            │
│     예: 고객 차원 (수백만 고객), 상품 차원 (수백만 SKU)                      │
│     → 정규화를 통해 데이터量を削減し保存空間 절약                              │
│                                                                             │
│  ✅ 차원属性의层次结构가 깊은 경우                                            │
│     예: 국가→도시→지역→점포 (4단계 계층)                                  │
│     → 각 수준을 정규화하여管理하기 쉽게 구성                                 │
│                                                                             │
│  ✅ 자주 변경되는 차원属性이 있는 경우                                        │
│     예: 상품 카테고리 구조 개편, 지역行政区划 변경                            │
│     → 정규화로 변경 影响範囲 최소화                                          │
│                                                                             │
│  ✅ 저장 공간이 제한적인 DW 환경                                             │
│                                                                             │
│  [스노우플레이크 비적합 상황]                                               │
│  ───────────────────                                                        │
│                                                                             │
│  ❌ 차원 테이블 규모가 작은 경우 (수천~수만 행)                              │
│     → 정규화의 효과가 微不足道                                               │
│                                                                             │
│  ❌ 조회 성능이 중요한 경우 (실시간 BI 대시보드)                             │
│     → 조인 오버헤드가 사용자 경험 저하                                       │
│                                                                             │
│  ❌ 단순하고 직관적인 모델을 원하는 경우                                     │
│     → 개발자와 사용자의 이해难度 증가                                         │
│                                                                             │
│  [Hybrid 접근: 스타 + 스노우플레이크 혼합]                                  │
│  ─────────────────────────────────────────                                  │
│                                                                             │
│  ┌─────────────────────────────────────────────────────────────────────┐ │
│  │  모든 차원을同一하게 스노우플레이크하거나 스타로 가지는 것이 아니라,     │ │
│  │  차원별 특성에 따라 선택적으로 적용                                       │ │
│  │                                                                       │ │
│  │  ┌─────────────────────────────────────────────────────────────┐   │ │
│  │  │  차원            │ 적용 방식    │ 이유                         │   │ │
│  │  │  ────────────────────────────────────────────────────────│   │ │
│  │  │  Time (시간)     │ 스타        │ 크기 작고 변경 거의 없음      │   │ │
│  │  │  Store (점포)    │ 스노우플레이크│ 계층 깊고 변경 있을 수 있음   │   │ │
│  │  │  Product (상품)  │ 하이브리드   │ 카테고리만 정규화, 브랜드는 비정규│ │ │
│  │  │  Customer (고객) │ 스노우플레이크│ 属性 많고 변경 있을 수 있음   │   │ │
│  │  └─────────────────────────────────────────────────────────────┘   │ │
│  │                                                                       │ │
│  └─────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

스노우플레이크 조회 예시

┌─────────────────────────────────────────────────────────────────────────────┐
│                    스노우플레이크 스키마 조회 예시                               │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  [예제 질의: 카테고리별 매출]                                               │
│  ─────────────────────────────────────────────────────────                   │
│                                                                             │
│  -- 스타 스키마 (간단한 조인)                                               │
│  SELECT                                                                 │
│    p.category,                                                             │
│    SUM(f.sales_amt) AS total_sales                                        │
│  FROM fact_sales f                                                        │
│  JOIN dim_product p ON f.product_key = p.product_key                      │
│  GROUP BY p.category;                                                     │
│                                                                             │
│  -- 스노우플레이크 (복잡한 조인)                                            │
│  SELECT                                                                 │
│    c.category_name,                                                        │
│    SUM(f.sales_amt) AS total_sales                                        │
│  FROM fact_sales f                                                        │
│  JOIN dim_product p ON f.product_key = p.product_key       -- 1차 조인     │
│  JOIN dim_sub_category sc ON p.sub_cat_key = sc.sub_cat_key -- 2차 조인   │
│  JOIN dim_category c ON sc.category_key = c.category_key    -- 3차 조인    │
│  GROUP BY c.category_name;                                                │
│                                                                             │
│  [조인 경로 비교]                                                          │
│  ────────────────                                                          │
│                                                                             │
│  스타 스키마:                                                              │
│  ┌─────────┐      ┌─────────┐                                            │
│  │  Fact   │─────▶│  Dim    │ ────▶ 결과                                 │
│  │         │  1   │ Product │                                            │
│  └─────────┘      └─────────┘                                            │
│                    (단일 조인)                                              │
│                                                                             │
│  스노우플레이크:                                                           │
│  ┌─────────┐      ┌─────────┐      ┌─────────┐      ┌─────────┐         │
│  │  Fact   │─────▶│  Dim    │─────▶│ Sub_Cat │─────▶│ Category│         │
│  │         │  1   │ Product │  2   │         │  3   │         │         │
│  └─────────┘      └─────────┘      └─────────┘      └─────────┘         │
│                    (3단계 조인)                                             │
│                                                                             │
│  ※ 스노우플레이크는 차원 계층 만큼 조인이 증가                               │
│  ※ 조인이 增加할수록 쿼리 성능 저하 (특히 대규모 데이터)                      │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

[다이어그램 해설] 스노우플레이크 스키마는 데이터 중복을 제거하고 관리를 용이하게 하는 장점이 있지만, 조인이 增加하여 쿼리 성능이 저하되는 단점이 있다. Kimball은 대부분의 DW에서 스타 스키마를 권장하며, 스노우플레이크는 차원이 매우 크거나 관리가 복잡한 제한된 경우에만 적용할 것을 조언한다. 실무에서는 Hybrid 접근(일부 차원만 정규화)을 통해 장점만 취하는 전략도 흔히 사용된다.

📢 섹션 요약: 스노우플레이크 스키마는 정규화를 통해 데이터 중복을 제거하지만, 차원 계층 만큼 조인이 증가하여 查询 성능이 저하되는 트레이드오프가 있다.


Ⅲ. 결론

스노우플레이크 스키마는 스타 스키마의 차원 테이블을 정규화하여 데이터 중복을 제거하고 저장 공간을 절약하는 차원 모델링 기법이다. 차원 속성의 계층을 분리하여 관리함으로써 데이터 일관성을 향상시키지만, 조인 경로가 增加하여 查询 성능이 저하되는 단점이 있다. Kimball은 대부분의 DW에서 스타 스키마를 기본으로 사용할 것을 권장하며, 스노우플레이크는 차원이 매우 크거나 자주 변경되는 제한된 상황에Selective하게 적용할 것을 조언한다. 실무에서는 차원별 특성에 따라 스타와 스노우플레이크를 혼합하는 Hybrid 접근이 흔히 사용된다.

📢 섹션 요약: 스노우플레이크 스키마는 정규화를 통해 데이터 관리를 용이하게 하지만, 조인 오버헤드로 인한 查询 성능 저하가 주요 단점이다.


핵심 인사이트 ASCII 다이어그램 (Concept Map)

┌─────────────────────────────────────────────────────────────────────────────┐
│                    Snowflake Schema Concept Map                                │
│                                                                             │
│              ┌─────────────────────────────────┐                           │
│              │     Snowflake Schema            │                           │
              │      (스노우플레이크 스키마)       │                           │
              └───────────────┬─────────────────┘                           │
│                              │                                               │
│                              ▼                                               │
│                   ┌─────────────────┐                                      │
│                   │  Fact Table    │                                      │
│                   │  (팩트 테이블)   │                                      │
│                   └────────┬────────┘                                      │
│                            │                                               │
│              ┌─────────────┴─────────────┐                                 │
│              ▼                           ▼                                  │
│       ┌─────────────┐             ┌─────────────┐                         │
│       │    Dim      │             │    Dim      │                         │
│       │   (정규화)   │             │  (정규화)   │                         │
│       └──────┬──────┘             └─────────────┘                         │
│              │                                                        │
│              ▼                                                        │
│       ┌─────────────┐                                                 │
│       │  Sub-Dim   │                                                 │
│       │ (서브차원)  │                                                 │
│       └──────┬──────┘                                                 │
│              │                                                        │
│              ▼                                                        │
│       ┌─────────────┐                                                 │
│       │ Sub-Sub-Dim │                                                 │
│       └─────────────┘                                                 │
│                                                                             │
│  장점: 중복 제거 | 일관성 | 저장 공간 절약                                   │
│  단점: 조인 증가 | 성능 저하 | 관리 복잡성                                   │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

참고

  • 스노우플레이크 스키마는 차원 테이블을 정규화한 형태이다.
  • 데이터 중복을 제거하고 저장 공간을 절약할 수 있다.
  • 조인 경로가 增加하여 查询 성능이 저하될 수 있다.
  • 데이터 일관성과 관리 용이성이 향상된다.
  • 대부분의 DW에서는 스타 스키마가 기본이다.
  • 차원이 매우 큰 경우에만 제한적으로 적용 권장.
  • 실무에서는 Hybrid 접근(스타+스노우플레이크 혼합)이 흔히 사용된다.