Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

データレイクのベストプラクティス

スタートガイドでは、Apache IcebergDelta LakeApache HudiApache Paimon を初めてクエリする手順を説明します。セットアップが完了したら、このページを使って適切なアクセスパターンを選び、クエリパフォーマンスを最適化し、本番環境でデータレイクのクエリをデバッグしてください。

アクセス方法を選択する

アクセス方法 使用するケース
テーブル関数 既知のパスに対してアドホッククエリを実行する場合 icebergS3(), deltaLake(), hudi(), paimon()
テーブルエンジン カタログなしで、同じパスに対して繰り返しクエリを実行する場合 IcebergS3, DeltaLake, Hudi
DataLakeCatalog データベースエンジン カタログを使用する本番ワークロードや、多数のテーブルをまたぐフェデレーテッドクエリ AWS Glue, Unity Catalog, REST カタログ

テーブル関数

保存先がわかっていて永続テーブルの定義が不要な場合は、ストレージのパスと認証情報をインラインで指定します。

SELECT count()
FROM icebergS3('https://my-bucket.s3.amazonaws.com/warehouse/my_table/')
WHERE event_date >= today() - 7

AWS S3 と GCS には S3 バリアントを使用します。Azure とローカルファイルシステムには専用のバリアント (icebergAzureicebergLocal、および他のフォーマットの対応する同等物) があります。完全な一覧については、直接クエリ を参照してください。

Paimon では、テーブル関数と実験的なテーブルエンジンが提供されています。

テーブルエンジン

同じパスに対して繰り返しクエリを実行する場合は、テーブルエンジンを使ってテーブルを作成します。ClickHouse はパスと認証情報をテーブルのメタデータに保存するため、毎回関数呼び出しを組み立て直すことなく、通常のテーブル名に対してクエリを実行できます。

CREATE TABLE events
    ENGINE = IcebergS3('https://my-bucket.s3.amazonaws.com/warehouse/events/')

SELECT count() FROM events WHERE event_date = today()

テーブルエンジンは、データキャッシュメタデータキャッシュ を含め、テーブル関数と同じ読み取り機能をサポートしています。データが ClickHouse 内で複製されることはありません。チームでアクセスを共有する場合や、同じテーブルに対して定期的なジョブを実行する場合は、テーブルエンジンが便利です。

DataLakeCatalog データベースエンジン

外部のデータカタログにテーブルを登録したら、ClickHouse を一度接続するだけで済みます。接続の作成後にアップストリームで追加されたテーブルも含め、すべてのカタログテーブルが自動的に ClickHouse テーブルとして表示されます。

CREATE DATABASE my_lake
ENGINE = DataLakeCatalog
SETTINGS
    catalog_type = 'glue',
    region = 'us-east-1',
    aws_access_key_id = '<key>',
    aws_secret_access_key = '<secret>'

SELECT count() FROM my_lake.`analytics.events`

多数のテーブルを管理する場合や複数のカタログを扱う場合は、個別にテーブル定義を作成するよりも、この方法のほうがスケーラブルです。カタログへの接続カタログガイド を参照してください。

必要な設定

多くのインテグレーションでは、初回利用前に機能フラグが必要です。CREATE DATABASE が権限エラーで失敗する場合は、サービスのバージョンを確認してください。

カタログ接続では、カタログタイプごとに専用のフラグがあります。概要については カタログへの接続 を、設定の詳細については DataLakeCatalog reference を参照してください。各カタログのセットアップ手順は カタログガイド にあります。

書き込みでは、Iceberg で allow_insert_into_iceberg が必要です (25.7+、26.2 以降はベータ) 。詳しくは データレイクへの書き込み を参照してください。Delta Lake で allow_delta_lake_writes が必要です (25.9+) 。サポートマトリクス には、各フォーマットと操作にどのフラグが適用されるかが示されています。

クエリパフォーマンスを向上させる

このページのバージョン番号は、ClickHouse のリリースバージョン (Cloud およびセルフマネージド) に対応しています。設定や機能を有効にする前に、ご利用中のサービスのバージョンを確認してください。

Lake のクエリパフォーマンスは、ClickHouse がオブジェクトストレージから読み取るメタデータの量と Parquet ファイル数に左右されます。他の ClickHouse テーブルと同様に、パーティションカラムで絞り込み、取得するカラムを少なくすることで、クエリパフォーマンスを向上できます。

クエリの習慣

WHERE 句では、パーティションカラムに対してフィルタを指定します。Iceberg と Delta Lake はパーティションのメタデータを保持しているため、ClickHouse はクエリプランの作成時に無関係なファイルをスキップできます。フィルタ対象がパーティション仕様に含まれないカラムの場合、ClickHouse は一致するすべてのファイルをスキャンします。

隠しパーティション化 を使用する Icebergテーブルでは、別個のパーティションカラムや変換後のフィールド名ではなく、テーブルスキーマ内の 元のカラム に対してフィルタを指定してください。テーブルが day(event_time) でパーティション化されている場合は、event_time に条件を追加します。ClickHouse はそのフィルタから、Iceberg の partition spec を使ってパーティションプルーニングを導き出します。パーティションプルーニングIceberg spec を参照してください。

SELECT count()
FROM my_lake.`logs.application`
WHERE event_time >= '2026-03-01'
  AND event_time < '2026-03-02'

SELECT * ではなく、必要なカラムだけを指定してください。ClickHouse はオブジェクトストレージから Parquet をカラム単位で読み取るため、必要なカラムだけを選択すると、転送および解凍するバイト数を削減できます。

選択性の高いフィルターは WHERE に置いてください。ClickHouse 26.2+ では、PREWHERE が Iceberg やその他のレイクテーブルの読み取りでもサポートされており、残りのカラムを読む前に Parquet レイヤーでフィルタリングを行えます。パーティションプルーニングは、PREWHERE だけでなく、引き続きパーティションの元となるカラムに対するフィルタリングに依存します。

位置 deletes または等価 deletes が多い Iceberg テーブルでは、スキャン時に merge-on-read フィルタリングが適用されます。マニフェストのプルーニングだけから想定されるよりも、ファイルごとの処理が増えると考えてください。

マルチノード構成では、cluster table functions を使用して、レプリカ間でファイル読み取りを分散してください。

マルチノードクラスターでの並列読み取り

ClickHouse Cloud とセルフマネージドのマルチノードサービスでは、レイク向けテーブル関数のクラスター版によって Parquet ファイルの読み取りがレプリカ間に分散されます。イニシエーターノードは、ファイルをワーカーに並列に振り分けます。大規模なテーブルに対するバッチ読み取りや定期ロードには、クラスター版を使用してください。シングルノードのデプロイメントでは、通常のテーブル関数で十分です。

クラスター名を第1引数として渡します (ClickHouse Cloud では 'default') 。対応フォーマットごとにクラスター版が用意されています。

フォーマット クラスター関数
Iceberg icebergS3Cluster(), icebergAzureCluster()
Delta Lake deltaLakeCluster(), deltaLakeAzureCluster()
Hudi hudiCluster()
Paimon paimonS3Cluster()

クラスター読み取りは、ほかのパフォーマンス設定と組み合わせることもできます。

バッチ読み取りの対象をスナップショットに限定する

レイクテーブルからバッチ読み込みを繰り返す場合は、毎回テーブル全体を再読み取りするのではなく、各実行の対象をスナップショットの範囲に限定してください。範囲を指定しないと、ClickHouse は実行のたびにすべてのバージョンとファイルをスキャンする可能性があり、オブジェクトストレージの読み取り量とクエリ時間が増加します。

前回正常に読み込みが完了した際のスナップショット識別子を保存し、次回の実行ではそれを下限として使用します。

Parquetファイルをローカルにキャッシュする

どちらのフォーマットでも、クエリ間で頻繁に使われる Parquet ファイルをローカルディスクに保持するために、enable_filesystem_cache を利用できます。セルフマネージド環境では、この設定の書き込み先となるストレージを確保するため、サーバー設定で ファイルシステムキャッシュディスク を構成してください。ClickHouse Cloud ではキャッシュは自動的に管理されます。ベンチマーク時には、キャッシュヒットによって実行ごとの差異が見えにくくならないよう、enable_filesystem_cache = 0 を設定してください。

Apache Iceberg

Iceberg の読み取り最適化のほとんどは、デフォルトで有効になっています。以下の設定では、パーティションプルーニング、メタデータキャッシュ、カタログとの往復通信を制御できます。

読み取り設定

設定 導入時期 デフォルト 注記
use_iceberg_partition_pruning 25.1 25.6 以降 1 マニフェスト内のパーティションのメタデータを使って、データファイルをスキップします
use_iceberg_metadata_files_cache 25.4 1 マニフェストリストとメタデータ JSON をメモリにキャッシュします
iceberg_metadata_staleness_ms 26.3 0 クエリ設定です。毎回カタログを呼び出す代わりに、この時間枠より新しい場合はキャッシュされたメタデータを使用します
iceberg_use_version_hint 25.6 直接パスアクセス時のメタデータ解決を高速化するために version-hint.text を読み取ります

カタログのレイテンシを抑える

カタログに接続されたIcebergテーブルでは、キャッシュしない限り、クエリごとにメタデータのフェッチが発生します。次の2つの設定を組み合わせて使います (26.4+) :

  1. テーブル作成時に iceberg_metadata_async_prefetch_period_ms を設定し、バックグラウンドでメタデータを事前フェッチします。
  2. クエリで iceberg_metadata_staleness_ms (26.3+) を設定し、カタログとの往復通信を省く代わりに、やや古いメタデータを許容します。
CREATE TABLE events
    ENGINE = IcebergS3('https://my-bucket.s3.amazonaws.com/warehouse/events/')
SETTINGS iceberg_metadata_async_prefetch_period_ms = 60000;

SELECT count()
FROM events
SETTINGS iceberg_metadata_staleness_ms = 60000;

0staleness 値では、常に最新のメタデータを取得します。テーブルの変更頻度が低く、読み取り負荷の高いワークロードでは、この期間を長くしてください。

ClickHouse が誤ったメタデータファイルを選択する場合 (テーブルパスに複数の .metadata.json ファイルがある場合) は、テーブル作成時に iceberg_metadata_file_path (25.4+) または iceberg_metadata_table_uuid を使って参照先を固定してください。メタデータファイルの解決 を参照してください。

タイムトラベル

iceberg_timestamp_ms または iceberg_snapshot_id (いずれも 25.4+) を使用すると、過去時点のスナップショットを読み取れます。同じクエリで両方を設定しないでください。ID を選択する前に、system.iceberg_history (25.6+) でスナップショットの系統を確認してください。繰り返しのバッチロードについては、バッチ読み取りをスナップショットに制限する を参照してください。

SELECT count()
FROM my_iceberg_table
SETTINGS iceberg_timestamp_ms = 1714636800000

Iceberg への書き込み

allow_insert_into_iceberg (25.7+、26.2 以降はベータ) に加え、INSERT 時の出力ファイルサイズとパーティション数を制御することもできます。

Setting Since Purpose
iceberg_insert_max_rows_in_data_file 25.9 出力データファイルあたりの行数上限
iceberg_insert_max_bytes_in_data_file 25.9 出力データファイルあたりのバイト数上限
iceberg_insert_max_partitions 25.12 1 回の INSERT で書き込むパーティション数の上限

データレイクへの書き込みIceberg エンジンのリファレンス を参照してください。

Delta Lake

バージョン 25.6 以降、ClickHouse は Delta Lake Rust カーネルを通じて、S3 および GCS 上の Delta Lake を読み取ります。この設定は、バージョン 26.8 以降では allow_delta_kernel_rs、バージョン 25.5 から 26.7 では allow_experimental_delta_kernel_rs です。Azure Blob Storage ではカーネルが無効になっているため、従来の reader を使用して deltaLakeAzure() を利用してください。カーネルを使用しない場合、パーティションプルーニング、変更データフィード、スナップショットバージョン の読み取りは利用できません。

Delta Kernel

Delta kernel 設定は、パーティションプルーニング、変更データフィード、スナップショット バージョンの読み取りを利用するには有効にする必要があります。25.5 以降では、S3 と GCS でデフォルトで有効です。明示的に有効化する場合は、ClickHouse のバージョンに対応する名前を使用してください。

バージョン 26.8 以降の場合:

SET allow_delta_kernel_rs = 1;

バージョン 25.5 ~ 26.7 の場合:

SET allow_experimental_delta_kernel_rs = 1;

読み取り設定

設定 導入 デフォルト 注記
delta_lake_enable_engine_predicate 25.8 1 フィルタをカーネルにプッシュダウンしてパーティションプルーニングを行います。Delta Kernel が必要です
delta_lake_reload_schema_for_consistency 26.3 0 同時実行の書き込みでスキーマが変更される場合、各クエリの前にスキーマを再読み込みします
delta_lake_snapshot_start_version / delta_lake_snapshot_end_version 25.12 -1 2 つのスナップショットバージョン間の CDF の変更を読み取ります。アップストリームで CDF が有効になっている必要があります
delta_lake_snapshot_version 25.8 -1 単一の過去のスナップショットを読み取ります。最新を読むには -1 を設定します (0 も有効です)

deletion vectors を持つテーブル (26.2+) では、読み取り時に行レベルのフィルタリングが適用されます。ClickHouse はこれを自動的に処理しますが、DV の多いテーブルでは、スキャン時にファイルごとの処理負荷が増えます。

Delta の変更データフィード

2 つの Delta スナップショット間で変更された行のみを読み取るには、delta_lake_snapshot_start_versiondelta_lake_snapshot_end_version (25.12+) を設定します。テーブルでは、アップストリームで変更データフィード (delta.enableChangeDataFeed) が有効になっている必要があります。開始バージョンと終了バージョンの両方をクエリ設定で指定してください。終了バージョンだけを指定するとエラーになります。

SELECT *
FROM deltaLake('s3://my-bucket/warehouse/ga4_events/')
SETTINGS
    delta_lake_snapshot_start_version = 42,
    delta_lake_snapshot_end_version = 47

各回の読み込みが成功するたびに終了バージョンを保存し、次回の実行時にそれを開始バージョンとして渡します。結果には CDF のカラム (_change_type_commit_version_commit_timestamp) が含まれます。ターゲットテーブルに読み込む前に、これらを処理してください。一般的なスナップショットのパターンについては、バッチ読み取りをスナップショットにバインドするを参照してください。

Delta Lake への書き込み

allow_delta_lake_writes (25.9+) に加え、INSERT 時の出力ファイルサイズを制御できます。

設定 導入時期 目的
delta_lake_insert_max_rows_in_data_file 25.9 出力データファイルごとの行数上限
delta_lake_insert_max_bytes_in_data_file 25.9 出力データファイルごとのバイト上限
SET allow_delta_lake_writes = 1;

INSERT INTO my_delta_table
SETTINGS
    delta_lake_insert_max_rows_in_data_file = 1000000,
    delta_lake_insert_max_bytes_in_data_file = 134217728
SELECT * FROM source_table

書き込みには、S3 または GCS 上の Delta Kernel が必要です。例については、DeltaLake エンジン リファレンスを参照してください。

データレイククエリのデバッグ

遅いデータレイククエリや想定外の結果を返すクエリは、多くの場合、メタデータの読み取り、パーティションプルーニング、またはカタログへの接続に起因します。まずは以下のチェックを行い、必要に応じてフォーマット固有のメタデータログを使用してください。

カタログ接続を確認する

CREATE DATABASEDataLakeCatalog では認証情報は検証されません。カタログへの接続が切れていても、database 自体は存在し得ます。ClickHouse 26.4 以降では、軽量なヘルスチェックを実行してください。

CHECK DATABASE my_lake;

以前のバージョンでは、SHOW TABLES FROM my_lake を実行して接続できることを確認し、error メッセージを確認します。解決されたストレージ path と engine の種類を確認するには、バッククォートで囲んだ table 名を指定して SHOW CREATE TABLE を使用します。

SHOW CREATE TABLE my_lake.`db.table`;

カタログのテーブルがsystem.tablesに表示されない場合は、show_remote_databases_in_system_tables (25.8+) を有効にしてください。カタログのテーブルは、デフォルトではシステムのイントロスペクションの対象外になっています。26.6より前のバージョンでは、以前の名称であるshow_data_lake_catalogs_in_system_tablesを使用してください。

読み取られているファイルを確認する

Iceberg と Delta Lake では、読み取り時に毎回 仮想カラム (_path_file_size_time_etag) が公開されます。_path でグループ化すると、パーティションプルーニングが機能しているか、あるいはクエリが想定以上に多くのファイルをスキャンしているかを確認できます。隠しパーティション化を使用する Iceberg テーブルでは、別のパーティションカラムではなく、元のカラム (たとえば event_time) で絞り込んでください。

SELECT _path, count() AS rows
FROM my_lake.`logs.application`
WHERE event_time >= '2026-03-01'
  AND event_time < '2026-03-02'
GROUP BY _path
ORDER BY rows DESC;

スキャン量を確認する

フィルターの追加や設定の調整の前後で、system.query_logread_rowsread_bytes を比較します。ReadBufferFromS3BytesCachedReadBufferReadFromCacheBytes などの ProfileEvents を見ると、オブジェクトストレージ由来のデータ量とローカル cache 由来のデータ量を確認できます。query_logEXPLAIN の詳しい手順については、低速なクエリを診断する を参照してください。

ベンチマーク時には、キャッシュヒットによって実行ごとの差が見えにくくならないよう、enable_filesystem_cache を無効にしてください。

メタデータログ

ClickHouse には、メタデータレベルのデバッグ用システムテーブルが 3 つあります。ログの有効化はクエリ時のみにしてください。継続的な監視用途には適していません。

システムテーブル フォーマット 対応バージョン 有効化方法 用途
system.iceberg_metadata_log Iceberg 25.9 クエリで iceberg_metadata_log_level を有効化 読み込まれたメタデータファイルやパーティションプルーニングの判断を追跡
system.iceberg_history Iceberg 25.6 ClickHouse の Iceberg テーブルでは自動的に記録 タイムトラベルクエリの前にスナップショットの系譜を確認
system.delta_lake_metadata_log Delta Lake 25.10 クエリで delta_lake_log_metadata = 1 を設定 Delta Lake のメタデータファイルとスナップショット解決を追跡

ログを有効にしてクエリを実行し、ログを flush してから、その query_id のエントリを確認します。

SELECT count() FROM my_iceberg_table
SETTINGS iceberg_metadata_log_level = 'manifest_file_entry';

SYSTEM FLUSH LOGS iceberg_metadata_log;

SELECT content_type, file_path, pruning_status
FROM system.iceberg_metadata_log
WHERE query_id = '<previous_query_id>';

ClickHouse Cloud では、ログデータは各ノードにローカルです。レプリカ全体を通した状況を確認するには、clusterAllReplicas を使用してください。

Iceberg の詳細なログレベルでは、マニフェストリストとファイルのメタデータのキャッシュが無効になるため、同じテーブルに対する後続のクエリが遅くなります。詳細度を高くするのは、実際に調査しているときだけにしてください。Delta Lake の述語に関する問題については、カーネルがフィルターをプッシュダウンできない場合に即座に失敗させるため、delta_lake_throw_on_engine_predicate_error (25.8+) を有効にしてください。

カラムの詳細と詳細度オプションについては、iceberg_metadata_logdelta_lake_metadata_log のリファレンスページを参照してください。

次のステップ

Navigation