Snowflake는 데이터 플랫폼에서 유지 관리 작업 수행 필요성을 없애고 클라우드를 위한 데이터 모델링 방법론을 자유롭게 선택할 수 있도록 하여 계속해서 클라우드 데이터에 대한 표준을 설정하고 있습니다. 트랜잭션 격리를 고려해야 하는 시나리오가 있을 수 있으며 Data Vault를 위한 이러한 시나리오가 존재합니다. 바로 공통 허브 테이블입니다.

이것은 ‘Snowflake의 Data Vault 기법’ 시리즈의 8번째 글입니다.

  1. 불변 스토어, 가상 종료일
  2. Data Vault용 Snowsight 대시보드
  3. 특정 시점 구성 및 트리 연결
  4. 매우 큰 위성 테이블 쿼리
  5. 보기에 대한 작업 및 스트림
  6. 조건부 다중 테이블 INSERT 및 사용 위치
  7. 행 액세스 정책 및 멀티 테넌트
  8. Snowflake에서 허브 잠금
  9. 가상 웨어하우스 및 비용 분담(charge back)

이전 블로그 글에서는 수동 통합 개념을 살펴보았습니다. 비즈니스 객체 정의에 따라 공통 허브 테이블로 통합하면서 동시에 로드하려는 경우가 Data Vault 모델에 이상적인 상황입니다. Snowflake가 READ COMMITTED 트랜잭션 격리 수준인 경우, 독립적인 허브 테이블 로더가 로드 후에도 대상 허브 테이블에 동일한 무결성이 유지되도록 보장하는 방법은 무엇일까요? Snowflake에서 이것이 실현되는 방식과 그것이 Data Vault 모델에 어떤 의미가 있는지 살펴보겠습니다.

병렬 로딩과 결과적 일관성

위에 설명된 대로, 랜딩된 모든 소스 데이터는 스테이징되어 모델링된 허브, 링크, 위성 테이블로 로드됩니다. 

  • 위성 테이블은 단일 소스이며 정의된 부모 키, 로드 날짜, 설명 상태 내용에 의해 고유하게 됩니다. 
  • 링크 테이블은 다중 소스가 아니며 정의된 작업 단위에 의해 고유하게 됩니다.
  • 허브 테이블은 항상 다중 소스이며 비즈니스 객체에 의해 고유하게 됩니다.

위의 예제에서 각 소스가 공통 허브 테이블에 어떻게 로드되는지 주목하십시오. 허브 테이블에는 각 허브 로더가 발견한 것과 같은 무결성이 유지되어야 합니다. 비즈니스 객체의 고유 목록은 비즈니스 키, 비즈니스 키 충돌 코드, 멀티 테넌트 ID로 정의됩니다.

문제

문제는 조건부 다중 테이블 삽입에 대해 논의한 6번째 블로그 글인 조건부 다중 테이블 INSERT 및 사용 위치에서 설명한 것과 같습니다. 동일한 대상 허브 테이블에 로드를 시도하는 각 스레드가 정확히 동시에 실행되는 경우, READ COMMITTED 트랜잭션 격리의 특성으로 인해 각 스레드는 다른 스레드에서 오는 UNCOMMITTED 트랜잭션 없이 대상 테이블을 보여줍니다.  

문제

중복으로 인해 Data Vault 모델의 무결성이 깨어지고 정보 마트가 보이기 시작하며 이와 연관하여 데이터 구조도 손상되기 시작합니다.

솔루션

Snowflake는 실제로 테이블 잠금을 허용하며 구문은 간단합니다. SQL INSERT 문을 SQL MERGE 문으로 변경하면, MERGE 문에 정의된 대상 허브 테이블은 대상 테이블을 업데이트할 차례가 오면 잠기게 됩니다. 물론 이것은 허브 로더 템플릿이 변경되고 구성된 모든 허브 로더가 대신 SQL MERGE INTO 문을 사용한다는 것을 의미합니다. 

솔루션
   
 insert into HUB_TABLE
    select distinct 
        < HUB-COLUMNS … >
    from STAGED stg
    where not exists 
      (select 1
       from HUB_TABLE h
       where stg.HASH-KEY = h.HASH-KEY)
    
merge into HUB_TABLE h 
    using (select distinct 
        < HUB-COLUMNS … >
    from STAGED) stg 
   on h.HUB_KEY = stg.HUB_KEY
when not matched then 
    insert (< HUB-COLUMNS … >) 
     values (< HUB-COLUMNS … >)

세 개의 SQL 데이터 조작 언어(DML) 문으로 업데이트를 위해 Snowflake 테이블을 잠급니다.

  • SQL MERGE – 두 번째 테이블 또는 하위 쿼리의 값을 기반으로 테이블의 값을 삽입, 업데이트, 삭제합니다
  • SQL UPDATE – 대상 테이블의 지정된 행을 새 값으로 업데이트합니다
  • SQL DELETE – 테이블에서 행을 제거합니다

자동화라는 종합적 관점에서, 이전의 애니메이션 예제를 이제 다음과 같이 업데이트할 수 있습니다.

이 접근 방식에서 대기 시간이 늘어날까요? 아마 그럴 것입니다. 하지만 허브 테이블은 일반적으로 안티 세미 조인(anti-semi join)을 사용하여 한 번에 몇 개의 압축 레코드만 처리하기 때문에 아주 약간의 변화만 있을 것입니다. 이 접근 방식의 장점은 외부에서 정의된 세마포어를 사용하여 대상 테이블을 명시적으로 잠글 필요가 없다는 것입니다. 대신 Snowflake는 어떤 스레드를 먼저 처리할지 무작위로 결정하는데, 그래도 허브 테이블은 아무 문제 없이 잘 작동합니다!

허브 테이블에 있는 동안…

SQL MERGE 문은 SQL INSERT 및 UPDATE를 허용하여, 이전에 사용 중단된 Data Vault 아티팩트인 허브 및 링크 테이블의 ‘최종 확인 날짜(last seen date)’ 열을 탐색할 기회를 제공합니다. 허브 및 링크 테이블은 작고 짧은 경향이 있어서 이러한 테이블을 구성하는 마이크로 파티션의 수도 매우 적습니다. 허브 및 링크 테이블에 SQL UPDATE를 허용하면 되지 않을까요? 

맞습니다. SQL UPDATE는 비용이 많이 드는 운영입니다. 하지만 최소 하나의 설명 열에서 수백 개의 설명 열까지 볼 수 있는 위성 테이블도 마찬가지일 수 있습니다. 여기서도 여전히 SQL UPDATE는 권장되지 않습니다. ‘최종 확인 날짜’가 어느 위치에 있을 때 유용한지 보여주기 위해 이전 예제를 업데이트해 보겠습니다. 

   
merge into HUB_TABLE h 
    using (select distinct 
        < HUB-COLUMNS … >
    from STAGED) stg 
   on h. HUB_KEY = stg.HUB_KEY
 when not matched then 
    insert (< HUB-COLUMNS … >) 
     values (< HUB-COLUMNS … >)


    
merge into HUB_TABLE h 
    using (select distinct 
        < HUB-COLUMNS … >
    from STAGED) stg 
   on h. HUB_KEY = stg.HUB_KEY
   when matched then 
    update set h.LAST = stg.LAST
   when not matched then 
    insert (< HUB-COLUMNS … >) 
     values (< HUB-COLUMNS … >)

기타 Data Vault 아티팩트

다른 특정 Data Vault 아티팩트는 INSERT-ONLY 테이블 구조이기 때문에 아래의 특정 정보를 추적하기 위해 개발되었습니다.

  • 기록 추적 위성(Record Tracking Satellites, RTS) – 비즈니스 객체 또는 작업 단위를 볼 때마다 기록하도록 설계되었습니다. 
  • 상태 추적 위성(Status Tracking Satellites, STS) – 소스가 스냅숏으로 제공되는 경우 비즈니스 객체 또는 작업 단위가 소스에서 나타나거나, 업데이트되거나, 혹은 삭제되는 시기를 추적하도록 설계되었습니다.
  • 유효성 위성(Effectivity Satellites, EFS) – 드라이버 키와 결합하여, 관련된 비 드라이버 키에 대응하는 드라이버 키를 추적합니다.
SAT, RTS, STS, HUB의 최종 확인 날짜를 비교하십시오.

“최종 확인 날짜”는 마지막으로 발생한 비즈니스 객체나 작업 단위만을 기록하기 때문에, 다음 사항을 확인하기 위한 신뢰할 수 있는 소스는 아닙니다.

  • RTS에서 추적된 소스 발생 빈도
  • STS에서 추적된 소스 삭제
  • 현재 관계에 대해 추적해야 할 때의 관계 변경

키 구동과 유효성

관계있는 구동 엔터티의 유효성을 추적하는 비즈니스 날짜가 데이터 소스에 포함되어 있지 않거나, 데이터 소스에서 추적된 것과 다른 구동 엔터티의 유효성을 추적하려는 경우, 유효성 위성이 필요합니다. 링크 테이블의 LAST_SEEN_DATE 열은 가장 복잡한 Data Vault 패턴 중 하나를 필요로 하지 않고도 현재 관계가 무엇인지 알려줍니다. 다음 예제를 사용하여 더 자세히 살펴보겠습니다.

EFS를 사용하지 않으면 잃게 되는 것.

LAST_SEEN_DATE를 사용 시의 구동 키가 무엇이든 관계없이, 해당 구동 키 및 관계에 대한 현재의 활성 관계를 맺게 됩니다. 또한 단일 링크 테이블에서 추적하고자 하는 각 구동 키에 대해 여러 개의 유효성 위성을 배포할 필요가 없습니다. 그러나 구동 대 비 구동 키 관계의 과거 이동을 추적할 수는 없습니다. 그것은 (다시) 소스 시스템이 이 움직임을 제공하지 않는 한은 유효성 위성만의 배타적 영역입니다. 

잠글 것인가 잠그지 않을 것인가

항상 이런 시나리오를 직접 테스트하십시오! 이 기술의 이면에 있는 아이디어는 Snowflake 테크놀로지가 제공하는 것을 이용하여 단일 목적으로 Data Vault 자동화를 유지하는 것입니다. 

Python의 선(Zen of Python)에서 인용한 바와 같이, “문제를 해결할 단 하나의 명확하고 바람직한 방법이 있을 것입니다.”

  • 허브 로더는 단일 소스 파일에서 하나의 허브 테이블을 로드해야 합니다.
  • 링크 로더는 단일 소스 파일에서 하나의 링크 테이블을 로드해야 합니다.
  • 위성 로더는 단일 소스 파일에서 하나의 위성 테이블을 로드해야 합니다.
  • 랜딩된 콘텐츠의 스테이징은 한 가지 방식으로 수행해야 합니다.

자동화 목표 달성을 위해 Snowflake 테크놀로지를 활용하십시오.

추가 참고 자료

참고: 이 내용은 2022. 10. 27에 게시된 컨텐츠(Data Vault Techniques on Snowflake: Hub Locking on Snowflake)에서 번역되었습니다.