디멘젼 모델링은 크게 팩트 테이블과 디멘젼 테이블 두 가지로 구성됩니다. 그 중 디멘젼 테이블은 데이터를 다양한 각도로 볼 수 있게 해주기 때문에 디멘젼 모델링에서 핵심이라고 할 수 있겠죠.
이런 디멘젼 테이블에서의 속성들이 변하지 않는다면 큰 문제가 되지 않겠지만 만약 값이 변한다면 어떻게 될까요? 이를 참조하는 팩트 테이블에서도 굉장한 혼란이 올 것이고, 정확하게 분석을 할 수 없게 됩니다. 예를 들어, 어떤 상품의 품목에 변경이 있었다면 품목별 총 매출을 구할 때 해당 상품을 어떤 품목으로 집계할 것인지 혼란이 있을테죠.
이런 식으로 디멘젼 테이블 속성의 변화에 대응하기 위해 만든 방법론이 바로 오늘 다룰 Slow Changing Dimension(SCD) 입니다. 이름에서 알 수 있듯이 디멘젼 변화에 대응하는 방법의 종류를 다룬 것인데요. 총 8가지 종류가 있기 때문에 천천히 하나씩 다뤄보도록 하죠.
Base
SCD는 크게 베이스가 되는 base 방법과 이 베이스들을 섞어 만든 hybrid 방법론이 존재합니다. 사실 대부분은 이 베이스들만 사용하는 경우가 많기 때문에 이 부분만 잘 알고 있어도 SCD를 이해하는데 큰 문제가 없기는 합니다.
Type 0: Retain Original
•
디멘젼 속성이 절대 변하지 않습니다.
•
영구 식별자, 날짜와 같이 변경되지 않는 속성에 적합합니다.
Type 1: Overwrite
•
예전 속성이 새로운 속성으로 덮어쓰여집니다.
•
따라서 type1은 항상 최신 값을 가지고 있고 과거 데이터를 없애버립니다.
product_id | sku | description | department |
1 | ABC922-Z | IntelliKidz | Education |
product_id | sku | description | department |
1 | ABC922-Z | IntelliKidz | Strategy |
Type 2: Add New Row
•
새로운 속성을 추가합니다.
•
같은 속성에 대해 여러 개의 row가 생길 수 있으므로 유니크한 PK가 있어야 합니다.
•
이 방식은 레코드가 변경되었을 때 기존 레코드는 유지하면서 변경된 레코드를 추가하는 방식입니다. 따라서 이를 구분하기 위해 3개의 컬럼을 추가합니다.
◦
row effective date or date/time stamp: 레코드 유효기간 (시작일)
◦
row expiration date or date/time stamp: 레코드 유효기간 (종료일)
◦
current row indicator: 레코드가 현재 유효한 레코드인지
•
가장 노멀하게 사용되는 scd 방식이고, dbt snapshot에서도 이 방식을 채택하고 있습니다.
product_id | sku | description | department | row_effective_date | row_expiration_date | currenct_row_indicator |
1 | ABC922-Z | IntelliKidz | Education | 2022-02-14 | null | True |
product_id | sku | description | department | row_effective_date | row_expiration_date | currenct_row_indicator |
1 | ABC922-Z | IntelliKidz | Education | 2022-02-14 | 2024-09-10 | False |
2 | ABC922-Z | IntelliKidz | Strategy | 2024-09-11 | null | True |
Type 3: Add new attribute
•
열을 추가해주는 방식입니다.
•
그렇게 자주 사용하는 방식은 아니긴 하지만 동시에 레코드를 여러 각도에서 볼 수 있다는 장점이 있습니다.
•
레코드가 바뀔 때마다 컬럼이 추가되기 때문에 너무 예측 불가하게 바뀌는 상황에서는 맞지 않고, breaking change가 있는 상황에서는 유용하게 사용될 수 있습니다.
product_id | sku | description | prior_department | department |
1 | ABC922-Z | IntelliKidz | Education | Strategy |
•
만약 데이터가 예측가능한 리듬으로 바뀐다면 아래와 같이 여러 개의 속성을 가진 형태로도 만들 수 있습니다.
product_id | sku | description | current_department | 2023_department | 2022_department |
1 | ABC922-Z | IntelliKidz | Strategy | Education | Not Applicable |
Type 4
•
Type 4는 2가지 정의를 가지고 있습니다.
◦
정확히는 2가지 정의를 따로 가지고 있다기 보다는 타입 하나에 중요한 정의 2가지가 섞여있는 형태입니다.
◦
그래서 일단은 따로 설명은 하지만 2가지 정의가 함께 섞여 있는 형태라고 보면 될 것 같습니다.
Add Mini-Dimension
•
먼저 이 글은 Kimball의 Data Warehouse Toolkit을 중심으로 하기 때문에 책에 소개된 방식을 먼저 소개하려 합니다.
•
만약 디멘젼 사이즈가 너무 커져버리면 분석하기에 성능 상에 이슈가 있을 수 있습니다.
•
예를 들어 type2 같은 경우 변화가 있을 때마다 레코드가 추가되기 때문에 사이즈가 엄청나게 커질 수 있습니다.
•
type 4는 이런 문제를 해결하고자 predefine된 작은 디멘젼 테이블을 만들어 놓고 이를 활용하는 방식입니다.
demographics_key | age_band | purchase_frequency_score | income_level |
1 | 21-25 | Low | <$30,000 |
2 | 21-25 | Medium | <$30,000 |
3 | 21-25 | High | <$30,000 |
… | … | … | … |
142 | 26-30 | Low | <$30,000 |
… | … | … | … |
Add history table
•
사실 위의 방식을 먼저 적기는 했지만 일반적으로는 이 방식을 지칭하는 것 같습니다.
•
이 타입은 type 2가 거의 동일한데 유일한 차이점은 기존 테이블은 건드리지 않고 history 테이블을 따로 만드는 것 입니다.
Original
product_id | sku | description | department |
1 | ABC922-Z | IntelliKidz | Education |
▼
product_id | sku | description | department |
1 | ABC922-Z | IntelliKidz | Strategy |
History
product_id | sku | description | department | row_effective_date |
1 | ABC922-Z | IntelliKidz | Education | 2022-02-14 |
2 | ABC922-Z | IntelliKidz | Strategy | 2024-09-11 |
Hybrid
하이브리드는 각 베이스들을 섞어 사용하는 방법인데요. 현업에서는 이런 복잡한 방식보다는 베이스를 바탕으로 상황에 맞게 변형하여 사용하는 경우가 대부분 인 것 같습니다.
Type 5: Mini-Dimension and Type 1 Outrigger
•
type 5는 type 1+type 4라고 볼 수 있습니다.
•
미니 디멘젼을 만드는 것까지는 type 4와 동일하지만 모든 히스토리를 남기는 것과 다르게 type 1의 방식을 차용해 모든 속성을 overwrite 시킵니다.
Type 6: Add Type 1 Attributes to Type 2 Dimension
•
type 6는 type 1+type 2+type3 인데요.
•
type 2의 로우 추가, type 3의 컬럼 추가 방식을 기본으로 하여 type1의 기존 행 업데이트 방식까지 함께 하이브리드 되어 있습니다.
product_id | sku | description | historic department | current department | row_effective_date | row_expiration_date | currenct_row_indicator |
1 | ABC922-Z | IntelliKidz | Education | Critical Thinking | 2022-02-14 | 2023-03-09 | False |
2 | ABC922-Z | IntelliKidz | Strategy | Critical Thinking | 2023-03-10 | 2024-09-11 | False |
3 | ABC922-Z | IntelliKidz | Critical Thinking | Critical Thinking | 2024-09-11 | null | True |
Type 7: Dual Type 1 and Type 2 Dimensions
•
type 7은 type 1과 type 2를 함께 사용하는 방식인데요.
•
히스토리 테이블과 현재 상태를 담고 있는 테이블을 동시에 사용합니다.
product_id | sku | description | department | row_effective_date | row_expiration_date | currenct_row_indicator |
1 | ABC922-Z | IntelliKidz | Education | 2022-02-14 | 2023-03-09 | False |
2 | ABC922-Z | IntelliKidz | Strategy | 2023-03-10 | 2024-09-11 | False |
3 | ABC922-Z | IntelliKidz | Critical Thinking | 2024-09-11 | null | True |
product_id | sku | description | department |
1 | ABC922-Z | IntelliKidz | Critical Thinking |
2 | ABC922-Z | IntelliKidz | Critical Thinking |
3 | ABC922-Z | IntelliKidz | Critical Thinking |