조직들이 분석 작업을 Databricks로 통합하면서 종종 전통적인 데이터 웨어하우스 기법을 적응해야 합니다. 이 시리즈에서는 Databricks에서 차원 모델링, 특히 별 스키마를 어떻게 구현하는지 탐구합니다. 첫 번째 블로그는 스키마 디자인에 초점을 맞추었습니다. 이 블로그에서는 차원 테이블을 위한 ETL 파이프라인, 특히 천천히 변하는 차원(SCD) Type-1과 Type-2 패턴을 소개합니다. 마지막 블로그에서는 사실 테이블을 위한 ETL 파이프라인을 구축하는 방법을 보여드릴 것입니다.
지난 블로그에서, 우리는 사실 테이블과 그와 관련된 차원들을 포함하는 별 스키마를 정의했습니다. 우리는 특히 DimCustomer라는 차원 테이블을 강조했는데, 여기에 (공간을 절약하기 위해 일부 속성을 제거한) 그림이 있습니다:
이 표의 마지막 세 필드, 즉, StartDate, EndDate 그리고 IsLateArriving, 는 레코드 버전 관리를 돕는 메타데이터를 나타냅니다. 고객의 소득, 결혼 상태, 주택 소유, 가정 내 아이 수 등의 특성이 변경되면 해당 고객에 대한 새로운 레코드를 생성하려고 합니다. 이렇게 하면 FactInternetSales 에서의 온라인 판매 거래와 같은 사실이 해당 고객의 올바른 표현과 연결됩니다. 자연 (또는 비즈니스) 키, CustomerAlternateKey, 는 이러한 레코드 간에 동일하게 유지되지만 메타데이터는 다르게 되어, 고객의 해당 버전이 유효했던 기간을 알 수 있습니다. 대리 키, CustomerKey, 도 마찬가지로 우리의 사실이 올바른 버전에 연결될 수 있게 합니다.
주의: 대리 키는 일반적으로 사실과 차원을 연결하는 데 사용되므로, 차원 테이블은 종종 이 키를 기반으로 클러스터링됩니다. 정렬된 레코드에 b-tree 인덱스를 사용하는 전통적인 관계형 데이터베이스와 달리, Databricks는 액체 클러스터링이라는 고유한 클러스터링 방법을 구현합니다. 액체 클러스터링의 구체적인 내용은 이 블로그의 범위를 벗어나지만, 우리는 이 기능을 효과적으로 활용하기 위해 차원 테이블의 정의 중에 대리 키에 대해 CLUSTER BY 절을 일관되게 사용합니다.
속성이 변경됨에 따라 버전이 지정된 차원 레코드의 이 패턴은 Type-2 Slowly Changing Dimension (또는 간 단히 Type-2 SCD) 패턴으로 알려져 있습니다. Type-2 SCD 패턴은 클래식 차원 방법론에서 차원 데이터를 기록하는 데 선호됩니다. 그러나 차원 레코드의 변경 사항을 처리하는 다른 방법들도 있습니다.
차원 값이 변경될 때 가장 일반적으로 사용하는 방법 중 하나는 기존 레코드를 그 자리에서 업데이트하는 것입니다. 레코드의 버전은 한 번만 생성되므로, 비즈니스 키가 레코드의 고유 식별자로 유지됩니다. 성능과 일관성 등 여러 이유로, 우리는 여전히 대리 키를 구현하고 이러한 차원에 대한 사실 레코드를 이러한 키에 연결합니다. 그럼에도 불구하고, StartDate 와 EndDate 메타데이터 필드는 주어진 차원 레코드가 활성으로 간주되는 시간 간격을 설명하지만 필요하지 않습니다. 이것은 Type-1 SCD 패턴으로 알려져 있습니다. 우리의 스타 스키마에서 프로모션 차원은 Type-1 차원 테이블 구현의 좋은 예를 제공합니다:
그런데 Type-2 고객 차원에는 있지만 Type-1 프로모션 차원에는 없는 IsLateArriving 메타데이터 필드는 어떻게 될까요? 이 필드는 레코드가 늦게 도착했다는 것을 표시하는 데 사용됩니다. 늦게 도착한 레코드 는 사실 ETL 주기 동안 비즈니스 키가 나타나지만 이전 차원 처리 과정에서 해당 키에 대한 레코드가 없는 경우를 말합니다. Type-2 SCD의 경우, 이 필드는 늦게 도착한 레코드의 데이터가 차원 ETL 주기에서 처음 관찰될 때 레코드가 업데이트되어야 하며 (Type-1 SCD 패턴처럼) 그 후부터 버전이 지정되어야 함을 나타내는 데 사용됩니다. Type-1 SCD의 경우, 이 필드는 레코드가 어차피 업데이트되기 때문에 필요하지 않습니다.
주의: Kimball Group은 추가적인 SCD 패턴을 인식하며, 이들 대부분은 Type-1 및 Type-2 패턴의 변형과 조합입니다. Type-1 및 Type-2 SCD가 가장 자주 구현되는 패턴이며, 다른 패턴에서 사용되는 기법이 이들과 밀접하게 관련되어 있기 때문에, 이 블로그는 이 두 가지 차원 유형에만 제한합니다. Kimball Group이 인식하는 8가지 SCD 유형에 대한 자세한 정보는 Slowly Changing Dimension Techniques 섹션을 이 문서에서 확인해 주세요.
데이터가 제자리에서 업데이트되는 경우, Type-1 SCD 워크플로우 패턴은 이차원 ETL 패턴 중 가장 간단합니다. 이러한 유형의 차원을 지원하기 위해, 우리는 단순히:
Type-1 SCD 구현을 설명하기 위해, 우리는 지속적인 DimPromotion 테이블의 인구를 위한 ETL을 정의할 것입니다.
첫 번째 단계는 우리의 운영 시스템에서 데이터를 추출하는 것입니다. 우리의 데이터 웨어하우스는 Microsoft가 제공하는 AdventureWorksDW 샘플 데이터베이스를 기반으로 하고 있으므로, 우리는 AdventureWorks (OLTP) 샘플 데이터베이스 를 우리의 소스로 사용하고 있습니다. 이 데이터베이스는 Azure SQL Database 인스턴스에 배포되어 Databricks 환경에서 연합 쿼리를 통해 접근 가능하게 되었습니다. 그런 다음 추출은 간단한 쿼리(공간을 절약하기 위해 일부 필드가 삭제됨)를 통해 이루어지며, 쿼리 결과는 우리의 스테이징 스키마(여기서 보여지지 않는 권한 설정을 통해 우리 환경의 데이터 엔지니어만 접근 가능)에 있는 테이블에 유지됩니다. 이것은 우리가 이 환경에서 소스 시스템 데이터에 접근할 수 있는 많은 방법 중 하나입니다:
추가적인 데이터 클린징 단계가 필요하지 않다고 가정하면(우리는 UPDATE 나 다른 CREATE TABLE AS 문을 이용해 구현할 수 있습니다), 우리는 비즈니스 키를 기반으로 스테이징된 데이터와 차원 데이터를 매칭하는 MERGE 문을 사용하여 차원 데이터 업데이트/삽입 작업을 한 단계에서 처리할 수 있습니다:
여기에 쓰여진 문장에 대해 주목해야 할 중요한 점은, 스테이징과 발행된 차원 테이블 데이터 사이에 일치가 발견되면 기존 레코드를 업데이트한다는 것입니다. WHEN MATCHED 절에 추가 기준을 추가하여 스테이징의 레코드가 차원 테이블에서 발견된 정보와 다른 경우에만 업데이트를 제한할 수 있지만, 이 특정 테이블의 레코드 수가 상대적으로 적 기 때문에 여기에 표시된 상대적으로 간결한 로직을 사용하기로 결정했습니다. (우리는 추가적인 WHEN MATCHED 로직을 DimCustomer, 더 많은 데이터를 포함하고 있기 때문에 사용할 것입니다.)
Type-2 SCD 패턴은 약간 더 복잡합니다. 이러한 유형의 차원을 지원하려면 다음을 수행해야 합니다:
Type-1 SCD 패턴과 마찬가지로, 우리의 첫 번째 단계는 소스 시스템에서 데이터를 추출하고 정제하는 것입니 다. 위와 같은 접근 방식을 사용하여, 연합 쿼리를 발행하고 추출된 데이터를 우리의 staging 스키마의 테이블에 유지합니다:
이 데이터가 도착하면, 이제 우리는 차원 테이블과 비교하여 필요한 데이터 수정을 할 수 있습니다. 이 중 첫 번째는 이전 사실 테이블 ETL 프로세스에서 늦게 도착한 것으로 표시된 레코드를 업데이트하는 것입니다. 이 업데이트는 늦게 도착한 것으로 표시된 레코드에 한정되며, IsLateArriving 플래그는 업데이트와 함께 재설정되어 이 레코드들이 앞으로 일반적인 Type-2 SCD처럼 동작하게 됩니다:
다음 데이터 수정 세트는 버전이 필요한 레코드를 만료시키는 것입니다. EndDate 값을 우리가 다음 단계에서 구현할 새 레코드 버전의 StartDate 와 일치시키는 것이 중요합니다. 그래서 우리는 이 두 단계 사이에서 사용될 타임스탬프 변수 를 설정할 것입니다:
참고: 사용 가능한 데이터에 따라, 원본 시스템에서 발생하는 EndDate 값을 사용할 수 있으며, 이 경우에는 여기에서 보여준 것처럼 변수를 반드시 선언하지 않아도 됩니다.
WHEN MATCHED 절에서 사용된 추가 기준에 주의하십시오. 이 문장에서는 하나의 작업만 수행하므로, 이 로직을 ON 절로 이동시킬 수 있지만, 우리는 이를 차원 레코드의 현재 버전과 일치하는 핵심 매칭 로직에서 분리하여 명확성과 유지 관리성을 유지하였습니다.
이 로직의 일부로, 우리는 equal_null() 함수를 많이 사용하고 있습니다. 이 함수는 첫 번째 값과 두 번째 값이 같거나 둘 다 NULL일 때 TRUE를 반환하고, 그렇지 않으면 FALSE를 반환합 니다. 이는 열별로 변화를 찾는 효율적인 방법을 제공합니다. Databricks가 NULL 의미론을 어떻게 지원하는지에 대한 자세한 내용은 이 문서를 참조하십시오.
이 단계에서, 차원 테이블의 기존 버전 레코드는 만료되어 종료 날짜가 지정되었습니다.
이제 새로운 레코드를 삽입할 수 있습니다. 실제로 새로운 것과 새로 버전화된 것 모두:
이전과 마찬가지로, 이것은 INSERT 문을 사용하여 구현되었을 수 있지만, 결과는 동일합니다. 이 문장을 사용하여, 스테이징 테이블에 있는 레코드 중 차원 테이블에 만료되지 않은 해당 레코드가 없는 레코드를 식별했습니다. 이 레코드들은 단순히 이 테이블에 존재할 수 있는 만료된 레코드와 일관된 StartDate 값으로 삽입됩니다.
차원이 구현되고 데이터로 채워지면, 이제 우리는 사실 테이블에 집중할 수 있습니다. 다음 블로그에서는 이러한 테이블에 대한 ETL이 어떻게 구현될 수 있는지 보여드릴 것입니다.
Databricks SQL에 대해 더 알아보려면 우리의 웹사이트 를 방문하거나 문서를 읽어보세요. 또한 Databricks SQL의 제품 투어를 확인해보세요. 만약 당신이 기존의 창고를 고성능, 서버리스 데이터 창고로 이전하고자 하며, 훌륭한 사용자 경험과 더 낮은 총 비용을 원한다면, Databricks SQL이 해결책입니다 — 무료로 시도해보세요.
(이 글은 AI의 도움을 받아 번역되었습니다. 원문이 궁금하시다면 여기를 클릭해 주세요)