メインコンテンツへスキップ
メインコンテンツへスキップ

SnowflakeからClickHouseへの移行

本ガイドでは、SnowflakeからClickHouseへデータを移行する方法について説明します。

SnowflakeとClickHouse間でデータを移行するには、転送用の中間ストレージとしてS3などのオブジェクトストアを使用する必要があります。移行プロセスでは、SnowflakeのCOPY INTOコマンドとClickHouseのINSERT INTO SELECTコマンドを使用します。

Snowflake からのデータエクスポート

Snowflake から ClickHouse への移行

Snowflake からデータをエクスポートするには、上図のように外部ステージを使用する必要があります。

次のスキーマを持つ Snowflake テーブルをエクスポートしたいとします:

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

このテーブルのデータを ClickHouse データベースに移動するには、まずこのデータを外部ステージにコピーする必要があります。データのコピー時には、中間フォーマットとして Parquet を使用することを推奨します。Parquet は型情報を共有でき、精度を保持し、圧縮率が高く、分析で一般的なネストした構造をネイティブにサポートするためです。

以下の例では、Snowflake で Parquet と必要なファイルオプションを表す名前付きファイルフォーマットを作成します。次に、コピーされたデータセットを格納するバケットを指定します。最後に、そのバケットにデータセットをコピーします。

CREATE FILE FORMAT my_parquet_format TYPE = parquet;

-- コピー先の S3 バケットを指定する外部ステージを作成
CREATE OR REPLACE STAGE external_stage
URL='s3://mybucket/mydataset'
CREDENTIALS=(AWS_KEY_ID='<key>' AWS_SECRET_KEY='<secret>')
FILE_FORMAT = my_parquet_format;

-- すべてのファイルに "mydataset" プレフィックスを付与し、最大ファイルサイズを 150MB に設定
-- カラム名を取得するには `header=true` パラメータが必須
COPY INTO @external_stage/mydataset from mydataset max_file_size=157286400 header=true;

約 5TB のデータセットに対して最大ファイルサイズを 150MB に設定し、同じ AWS us-east-1 リージョンにある 2X-Large の Snowflake ウェアハウスを使用した場合、S3 バケットへのデータコピーにはおよそ 30 分かかります。

ClickHouse へのインポート

データが中間オブジェクトストレージにステージングされたら、以下のように 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 テーブルスキーマ内の VARIANT 列と OBJECT 列は、デフォルトでは JSON 文字列として出力されます。そのため、ClickHouse に挿入する際には、これらをキャストする必要があります。

some_file のようなネストした構造は、Snowflake によるコピー処理の際に JSON 文字列へと変換されます。このデータをインポートするには、上記の JSONExtract 関数 を使用して、ClickHouse への挿入時にこれらの構造を Tuple 型に変換する必要があります。

データエクスポート成功のテスト

データが正しく挿入されたかをテストするには、新しいテーブルに対して SELECT クエリを実行するだけです。

SELECT * FROM mydataset LIMIT 10;