Snowflake에서 ClickHouse로 마이그레이션

Snowflake에서 ClickHouse로 마이그레이션

이 가이드는 Snowflake 데이터를 ClickHouse로 옮기는 방법을 보여줘요. 두 시스템 간 데이터 이동은 S3 같은 오브젝트 스토어를 중간 저장소로 사용하고, Snowflake의 COPY INTO와 ClickHouse의 INSERT INTO SELECT 명령에 의존해요.

출처: Migrate from Snowflake to ClickHouse

본문

이 가이드는 Snowflake에서 ClickHouse로 데이터를 마이그레이션하는 방법을 보여줘요.

Snowflake와 ClickHouse 사이에서 데이터를 마이그레이션하려면 전송을 위한 중간 저장소로 S3 같은 오브젝트 스토어를 사용해야 해요. 마이그레이션 과정은 Snowflake의 COPY INTO 명령과 ClickHouse의 INSERT INTO SELECT 명령에 의존하기도 해요.

1. Snowflake에서 데이터 내보내기

Snowflake에서 데이터를 내보내려면 위 다이어그램에 나온 것처럼 외부 스테이지(external stage)를 사용해야 해요. 다음과 같은 스키마를 가진 Snowflake 테이블을 내보낸다고 해 볼게요:

CREATE TABLE MYDATASET (
   timestamp TIMESTAMP,
   some_text varchar,
   some_file OBJECT,
   complex_data VARIANT,
) DATA_RETENTION_TIME_IN_DAYS = 0;

이 테이블의 데이터를 ClickHouse 데이터베이스로 옮기려면 먼저 이 데이터를 외부 스테이지로 복사해야 해요. 데이터를 복사할 때는 Parquet을 중간 포맷으로 권장해요. 타입 정보를 공유할 수 있고, 정밀도를 보존하며, 잘 압축되고, 분석에서 흔한 중첩 구조를 기본 지원하기 때문이죠.

아래 예시에서는 Snowflake에서 Parquet과 원하는 파일 옵션을 나타내는 named file format을 만들어요. 그리고 복사된 데이터셋이 들어갈 버킷을 지정해요. 마지막으로 데이터셋을 버킷으로 복사해요.

CREATE FILE FORMAT my_parquet_format TYPE = parquet;

-- Create the external stage that specifies the S3 bucket to copy into
CREATE OR REPLACE STAGE external_stage
URL='s3://mybucket/mydataset'
CREDENTIALS=(AWS_KEY_ID='<key>' AWS_SECRET_KEY='<secret>')
FILE_FORMAT = my_parquet_format;

-- Apply "mydataset" prefix to all files and specify a max file size of 150mb
-- The `header=true` parameter is required to get column names
COPY INTO @external_stage/mydataset from mydataset max_file_size=157286400 header=true;

약 5TB의 데이터셋에 최대 파일 크기 150MB이고, 같은 AWS us-east-1 리전에 있는 2X-Large Snowflake 웨어하우스를 사용하면, S3 버킷으로 데이터를 복사하는 데 약 30분이 걸려요.

2. ClickHouse로 가져오기

데이터가 중간 오브젝트 스토리지에 staged되면, s3 테이블 함수 같은 ClickHouse 함수로 데이터를 테이블에 삽입할 수 있어요. 이 예시는 AWS S3용 s3 테이블 함수를 사용하지만, Google Cloud Storage에는 gcs 테이블 함수, Azure Blob Storage에는 azureBlobStorage 테이블 함수를 사용할 수 있어요. 다음과 같은 대상 테이블 스키마를 가정할게요:

CREATE TABLE default.mydataset
(
  `timestamp` DateTime64(6),
  `some_text` String,
  `some_file` Tuple(filename String, version String),
  `complex_data` Tuple(name String, description String),
)
ENGINE = MergeTree
ORDER BY (timestamp)

그다음 INSERT INTO SELECT 명령을 사용해서 S3의 데이터를 ClickHouse 테이블로 삽입할 수 있어요:

INSERT INTO mydataset
SELECT
  timestamp,
  some_text,
  JSONExtract(
    ifNull(some_file, '{}'),
    'Tuple(filename String, version String)'
  ) AS some_file,
  JSONExtract(
    ifNull(complex_data, '{}'),
    'Tuple(filename String, description String)'
  ) AS complex_data,
FROM s3('https://mybucket.s3.amazonaws.com/mydataset/mydataset*.parquet')
SETTINGS input_format_null_as_default = 1, -- Ensure columns are inserted as default if values are null
input_format_parquet_case_insensitive_column_matching = 1 -- Column matching between source data and target table should be case insensitive

중첩 컬럼 구조에 대한 참고 사항: 원래 Snowflake 테이블 스키마의 VARIANTOBJECT 컬럼은 기본적으로 JSON 문자열로 출력돼서, ClickHouse에 삽입할 때 이들을 캐스팅해 줘야 해요. some_file 같은 중첩 구조는 Snowflake에서 복사될 때 JSON 문자열로 변환돼요. 이 데이터를 가져오려면 위에서 보여 준 것처럼 JSONExtract 함수를 사용해서 삽입 시점에 이 구조들을 Tuple로 변환해야 해요.

3. 데이터 내보내기가 성공했는지 테스트하기

데이터가 제대로 삽입되었는지 테스트하려면 새 테이블에서 SELECT 쿼리를 실행해 보면 돼요:

SELECT * FROM mydataset LIMIT 10;

더 알아보기 (Learn more)