천천히 변경되는 차원(SCD)은 시간 경과에 따른 데이터 웨어하우스의 차원 데이터 변경 사항을 관리하고 추적하기 위한 프레임워크 입니다. 이 프레임워크 데이터 SCD가 낮은 빈도로 발생하지만 시간상 뚜렷한 패턴 없는 변경 사항을 포함한다고 가정하기 때문에 차원을 '느리게 변화하는' 차원이라고 합니다. 데이터 웨어하우스에 대한 요구 사항이 데이터의 과거 상태를 기반으로 출력을 추적 하고 재현하는 기능을 다루는 경우 SCD를 사용합니다.
SCD의 일반적인 사용 사례 보고 입니다. 예시 를 들어, 재무 보고 시스템에서는 지난 달에 생성된 보고서의 집계된 값과 데이터 웨어하우스의 현재 버전 보고서의 집계된 값 간의 차이점을 설명해야 합니다.
SQL 에서 SCD의 다양한 구현을 "유형"이라고 합니다. 가장 기본적인 유형인 0 및 1 유형은 각각 데이터의 원래 상태 또는 데이터의 현재 상태 만 추적 합니다. 가장 일반적으로 적용되는 구현 2 유형은 세 개의 새 필드 validFrom
, validTo
및 최신 데이터 설정하다 에 대한 선택적 플래그(종종 isValid
또는 isEffective
라고 함)를 생성합니다.
SCD 유형
SCD 유형 | 설명 |
---|---|
0입력 | 원래 상태 만 유지하며 데이터는 변경할 수 없습니다. |
1입력 | 업데이트된 상태 및 기록 유지만 저장할 수 없습니다. |
2입력 | 새 문서 에 기록을 보관합니다. |
3입력 | 동일한 문서 의 새 필드에 기록을 보관합니다. |
4입력 | 기록을 별도의 컬렉션 에 보관합니다. |
6입력 | 2 유형과 3 유형의 조합입니다. |
MongoDB 의 SCD
관계형 데이터베이스 에 적용 동일한 방식으로 SCD 프레임워크 MongoDB 에 적용 할 수 있습니다. 천천히 변화하는 차원의 개념은 특정 사용 사례 에 맞게 선택되고 최적화된 데이터 모델 에서 문서별로 적용됩니다.
예시
항목 설정하다 의 가격을 저장하는 prices
컬렉션 생각해 보겠습니다. 환불된 금액은 구매 시점의 품목 가격과 일치해야 하므로 품목의 반환을 프로세스 하려면 시간 경과에 따른 품목 가격 변화를 추적 해야 합니다. 컬렉션 의 각 문서 에는 item
및 price
필드 있습니다.
db.prices.insertMany( [ { 'item': 'shorts', 'price': 10 }, { 'item': 't-shirt', 'price': 2 }, { 'item': 'pants', 'price': 5 }, ] )
바지의 가격이 5
에서 7
로 변경된다고 가정해 보겠습니다. 이 가격 변경을 추적 하려면 SCD 유형 2에 필요한 데이터 필드의 기본값 을 가정합니다. validFrom
의 기본값 은 01.01.1900
, validTo
는 01.01.9999
, isValid
의 기본값은 true
입니다. 'item': 'pants'
을 사용하여 객체 의 price
필드 변경하려면 바지의 현재 상태 나타내는 새 문서 삽입하고 이전에 유효한 문서 더 이상 유효하지 않도록 업데이트 .
let now = new Date(); db.prices.updateOne( { 'item': 'pants', "$or": [ { "isValid": false }, { "isValid": null } ] }, { "$set": { "validFrom": new Date("1900-01-01"), "validTo": now, "isValid": false } } ); db.prices.insertOne( { 'item': 'pants', 'price': 7, "validFrom": now, "validTo": new Date("9999-01-01"), "isValid": true } );
유효성 체인이 깨지는 것을 방지하려면 위의 두 데이터베이스 작업이 모두 동일한 타임스탬프에서 발생해야 합니다. 애플리케이션 의 요구 사항에 따라 위의 두 명령을 트랜잭션 으로 래핑하여 MongoDB 항상 두 변경 사항을 모두 적용하도록 할 수 있습니다. 자세한 내용은 트랜잭션을 참조하세요.
다음 작업은 pants
항목이 포함된 문서 의 최신 price
를 쿼리 방법을 보여 줍니다.
db.prices.find( { 'item': 'pants', 'isValid': true } );
특정 점 에 pants
항목이 포함된 문서 의 price
를 쿼리 하려면 다음 작업을 사용합니다.
let time = new Date("2022-11-16T13:00:00"); db.prices.find( { 'item': 'pants', 'validFrom': { '$lte': time }, 'validTo': { '$gt': time } } );
일부 필드의 변경 사항 추적
문서 의 일부 필드에 대한 시간 경과에 따른 변경 사항만 추적 해야 하는 경우 첫 번째 문서 에 필드 의 기록을 배열 로 포함하여 3 SCD 유형을 사용할 수 있습니다.
예시 를 들어, 다음 집계 파이프라인 pants
을(를) 나타내는 문서 에서 price
을(를) 7
(으)로 업데이트하고 price
의 이전 값을 이전 price
이(가) 유효하지 않게 된 시점의 타임스탬프와 함께 배열 에 저장합니다. priceHistory
:
db.prices.aggregate( [ { $match: { 'item': 'pants' } }, { $addFields: { price: 7, priceHistory: { $concatArrays: [ { $ifNull: [ '$priceHistory', [] ] }, [ { price: "$price", time: now } ] ] } } }, { $merge: { into: "prices", on: "_id", whenMatched: "merge", whenNotMatched: "fail" } } ] )
배열 크기가 너무 커지면 이 솔루션이 느려지거나 비효율적일 수 있습니다. 큰 배열을 피하려면 이상값 또는 버킷 패턴을 사용하여 스키마 설계할 수 있습니다.
아웃룩 Data Federation
위의 예는 문서 필드 변경 사항을 엄격하고 정확하게 표현하는 데 중점을 둡니다. 경우에 따라 기록 데이터 표시에 대한 요구 사항이 덜 엄격할 수 있습니다. 예시 들어 대부분의 경우 데이터의 현재 상태 에만 액세스 하면 되지만 데이터의 전체 기록에 대해 일부 분석 쿼리를 실행 해야 하는 애플리케이션 있을 수 있습니다.
이 경우 데이터의 현재 버전을 한 컬렉션 에 저장 하고 기록 변경 사항을 다른 컬렉션 에 저장할 수 있습니다. 그런 다음 MongoDB Atlas 연합 데이터베이스 기능을 사용하여 활성 MongoDB cluster 에서 기록 컬렉션 제거 할 수 있으며, 완전 managed 버전에서는 Online 보관 사용하여 제거할 수 있습니다.
기타 사용 사례
천천히 변화하는 차원은 데이터 웨어하우징에 유용하지만 이벤트 중심 애플리케이션에서 SCD 프레임워크 사용할 수도 있습니다. 다양한 유형의 카테고리에서 자주 발생하지 않는 이벤트가 있는 경우, 프로세스 에서 현재 상태 찾기 위해 데이터를 그룹화하거나 정렬해야 할 수 있으므로 카테고리별 최신 이벤트 찾는 데 비용이 많이 듭니다.
이벤트가 자주 발생하지 않는 경우 문서 당 이벤트 시간 외에도 다음 이벤트 시간을 저장 필드 추가하여 데이터 모델 수정할 수 있습니다. 새로운 날짜 필드 사용하면 특정 점 에 대한 검색 실행할 때 검색하려는 각 이벤트 쉽고 효율적으로 조회 할 수 있습니다.