02 계획과 설계
Snowflake 워크로드를 프로파일링하고, 마이그레이션이 실행할 아키텍처 결정을 내린다 — 엔진 선택, 정렬 키, 스키마 변환, 배포 웨이브, dbt 모델 설계.
시작 지점
모듈 01 완료 상태: Snowflake가 완전히 구축되고, CDC 스트림과 두 예약 태스크가 실행 중이고,
그리고 결정적으로 트립 프로듀서가 여전히 TRIPS_RAW에 분당 약 60건의 트립을 쓰고 있다.
계속 실행해 두어라. 이 모듈은 Snowflake에서 읽기만 한다. 약 90분과 Snowflake 크레딧 약
0.5개를 예상하라.
이유
ClickHouse 마이그레이션이 기대 이하의 성능을 내는 가장 흔한 이유는 튜닝 문제가 아니라 아키텍처 문제다. 팀은 데이터를 먼저 옮기고 설계는 나중에 생각한다. 잘못된 MergeTree 엔진이 조용히 틀린 결과를 만들어 낸다는 것, 또는 소스 스키마에서 복사한 정렬 키가 실제 쿼리 패턴을 무시한다는 것을 깨달을 때쯤이면 마이그레이션은 이미 "끝나" 있다. 이 모듈은 반대 순서를 강제한다. 실제로 가진 것을 프로파일링한 다음, 모듈 03이 그 어느 것도 실행하기 전에 모든 엔진, 정렬 키, 타입 매핑, 순서 결정을 — 문서로 — 명시화한다.
이 모듈은 또한 파트너들이 가장 건너뛰고 싶어 하는 모듈이다. 모듈 03의 setup.sh는
migration-plan.md를 확인하고 없거나 미완성이면 경고하지만, 절대 막지는 않는다 — 없이도
밀고 나갈 수 있다. 그렇게 하면 스스로 내린 적 없는 결정을 실행하는 모듈 03을 돌리게 된다.
왜 평범한 MergeTree가 아니라 그 엔진인지 모른 채 fact_trips가 ReplacingMergeTree로
올라오는 것을 보고, 쿼리 워크로드에서 어떻게 도출되었는지 모른 채 ORDER BY 키를 보고,
다른 워크로드에서 어떻게 도출할지 모른 채 dbt 설정의 delete_insert와 FINAL을 보고,
고객에게 설명하거나 재현할 수 없는 모듈 04의 벤치마크 속도 향상을 보게 된다. 여기서 쓰는
90분이 나머지 워크샵을 명령 복사에서 마이그레이션 이해로 바꿔 놓는다.
개념 — 내부 동작
이 모듈이 만들어 내는 모든 결정은 다섯 개 범주 중 하나에 속하고, 범주마다 워크시트가 있다.
- 엔진 계열 — 각 테이블의 쓰기 패턴에 어떤 MergeTree 변종이 맞는지: 추가 전용이면
평범한
MergeTree, CDC를 통해 업데이트를 받는 테이블이면ReplacingMergeTree, 미리 집계한 롤업이면AggregatingMergeTree. MergeTree 엔진을 참고하라. ORDER BY키 — ClickHouse에는 나중에 추가할 인덱스가 없다. 정렬 키는 소스 테이블의 primary key가 아니라 실제 쿼리 워크로드에서 단 한 번 선택된다.- 타입 매핑과 방언 격차 — Snowflake의
VARIANT,LATERAL FLATTEN,MERGE INTO는 직접적인 ClickHouse 대응물이 없어서 변환된 형태가 필요하다.QUALIFY는 예외다. ClickHouse는 v24.5부터 네이티브QUALIFY절을 갖고 있지만, 이 랩은QUALIFY가 없거나 그 이전인 ClickHouse 버전과 SQL 엔진으로 이식할 수 있기 때문에 여전히 서브쿼리 재작성을 가르친다. Snowflake vs ClickHouse를 참고하라. - dbt 모델 설계 — 모델별 머티리얼라이제이션, 엔진 설정, 증분 전략,
FINAL배치. dbt on ClickHouse를 참고하라. - 웨이브 순서 — 아직 하위 의존성이 없어서 먼저 옮길 수 있는 객체와 기다려야 하는 객체.
1단계 — Snowflake 환경 프로파일링
cd "$(git rev-parse --show-toplevel)/workshop_public/snowflake_migration_lab/02-plan-and-design"
source ../01-setup-snowflake/.env
./scripts/01_profile_snowflake.sh이 스크립트는 살아 있는 모듈 01 Snowflake 인스턴스에 대해 실행되며 네 개 섹션으로 이루어진
profile_report.md를 쓴다. 객체 인벤토리(행 수와 복잡도 등급이 붙은 모든 테이블, 뷰,
스트림, 태스크), 지난 7일간 총 경과 시간 기준 상위 10개 쿼리, 테이블 통계(행 수, 날짜
범위, null 비율, VARIANT 사용), 그리고 자동 감지된 스키마 호환성 격차다.
profile_report.md는 gitignore 대상이다 — 실행할 때마다 본인의 Snowflake 계정에서 새로
생성되므로 머신마다 다르고 커밋되지 않는다. 새로 클론한 곳에서 찾을 것으로 기대하지 말고,
직접 커밋하려 하지도 마라.
ACCOUNT_USAGE를 아직 쓸 수 없다면(1-3시간의 전파 지연이나 ACCOUNTADMIN 역할이 필요하다)
스크립트는 INFORMATION_SCHEMA로 폴백하고 측정할 수 없었던 것을 기록한다. Snowflake UI에서
scripts/02_query_history.sql을 직접 실행할 수도 있다.
2단계 — 다섯 개의 워크시트 작업
다섯 개의 워크시트를 순서대로 진행하라. 각 워크시트는 개념을 하나 가르치고, 실제 NYC Taxi 워크로드에 대한 객관식 문제를 제시한다. 모든 답은 선택하는 즉시 채점되며, 각 워크시트에는 채워진 표를 마이그레이션 계획에 붙여 넣을 수 있게 해 주는 "Copy as markdown" 버튼이 있다.
- 워크시트 1: MergeTree 엔진 선택 — 테이블별 엔진 계열과 엔진 선택
- 워크시트 2: 정렬 키 설계 — 쿼리 워크로드에서 도출한
ORDER BY - 워크시트 3: 스키마 변환 — 타입 매핑과 함수 변환
- 워크시트 4: 마이그레이션 웨이브 계획 — 의존성 순서와 웨이브 배정
- 워크시트 5: dbt 모델 설계 — 머티리얼라이제이션, 엔진, 증분 전략,
FINAL배치
답은 리포지토리가 아니라 브라우저의 로컬 스토리지에 저장된다 — 다른 머신으로 따라가지 않고, 사이트 데이터를 지우면 사라진다. 워크샵 중간에 노트북을 바꾸면 그쪽에서 워크시트를 다시 해야 한다.
3단계 — 마이그레이션 계획 작성
workshop_public/snowflake_migration_lab/02-plan-and-design/migration-plan.md를 열고 워크시트
답을 사용해 각 섹션을 채워라. 이 문서에는 열 개의 섹션이 있고, 맨 위에 다섯 개의 체크박스로
된 Completion Checklist가 있다.
- [ ] Engine selection: completed
- [ ] Sort key design: completed
- [ ] Schema translation: completed
- [ ] Migration wave plan: completed
- [ ] dbt model design: completed모듈 03의 setup.sh는 이 체크리스트를 확인하고 미완성이면 경고하지만, 진행을 막지는
않는다. 그래도 끝내는 것이 모듈 03의 결정을 임의적으로 느껴지는 대신 납득되게 만든다.
완료 확인 방법
다음이 모두 성립하면 완료다.
- 다섯 워크시트 모두 만점을 보여 준다 — 각 워크시트 하단의 점수 줄이
N/N correct로 표시된다. workshop_public/snowflake_migration_lab/02-plan-and-design/migration-plan.md의 Completion Checklist에 있는 모든 체크박스가 체크되어 있다.- 1단계에서 만든
profile_report.md가 디스크에 존재한다(gitignore 대상이므로git status에는 나타나지 않는다).
자신의 계획을 다 쓴 뒤에는 Worked example: a completed plan과 비교하라 — 같은 워크로드에 대해 완전히 채워진 계획이다. 스스로 충분히 생각하기 전에 채워 넣을 템플릿으로 쓰지 말고, 자신의 논리를 검증하고 다르게 선택한 곳을 이해하는 데 사용하라.
종료 상태
디스크에 채워진 migration-plan.md, 모든 체크박스가 체크된 상태, 그리고 그것을 뒷받침하는
완료된 다섯 개의 워크시트. Snowflake 프로듀서는 여전히 실행 중이다 — 모듈 03은 살아
움직이는 소스에서 데이터를 마이그레이션하며, 모듈 05의 컷오버는 마이그레이션 중 프로듀서가
Snowflake와 ClickHouse 사이에 만드는 정확한 공백을 측정한다. 지금 중지하지 마라.