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

S3 table engine

このエンジンは、Amazon S3 エコシステムと連携します。このエンジンは HDFS エンジンと類似していますが、S3 固有の機能を備えています。

CREATE TABLE s3_engine_table (name String, value UInt32)
    ENGINE=S3('https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/test-data.csv.gz', 'CSV', 'gzip')
    SETTINGS input_format_with_names_use_header = 0;

INSERT INTO s3_engine_table VALUES ('one', 1), ('two', 2), ('three', 3);

SELECT * FROM s3_engine_table LIMIT 2;
┌─name─┬─value─┐
│ one  │     1 │
│ two  │     2 │
└──────┴───────┘

テーブルの作成

CREATE TABLE s3_engine_table (name String, value UInt32)
    ENGINE = S3(path [, NOSIGN | aws_access_key_id, aws_secret_access_key,] format, [compression], [partition_strategy], [partition_columns_in_data_file])
    [PARTITION BY expr]
    [SETTINGS ...]

エンジンパラメータ

  • path — ファイルへのパスを含むバケット URL。読み取り専用モードでは ***?{abc,def}{N..M} というワイルドカードをサポートします。ここで NM は数値、'abc''def' は文字列です。詳細は下記を参照してください。
  • NOSIGN - 認証情報の代わりにこのキーワードが指定された場合、すべてのリクエストは署名されません。
  • format — ファイルのフォーマット
  • aws_access_key_id, aws_secret_access_key - AWS アカウントユーザーの長期認証情報。これを使用してリクエストを認証できます。パラメータは省略可能です。認証情報が指定されていない場合、設定ファイルの値が使用されます。詳細は Using S3 for Data Storage を参照してください。
  • compression — 圧縮タイプ。サポートされる値: none, gzip/gz, brotli/br, xz/LZMA, zstd/zst。パラメータは省略可能です。デフォルトではファイル拡張子から圧縮方式を自動検出します。
  • partition_strategy – オプション: WILDCARD または HIVEWILDCARD では、パス内に {_partition_id} を含める必要があり、これがパーティションキーに置き換えられます。HIVE ではワイルドカードは使用できず、パスはテーブルのルートであるとみなし、Snowflake ID をファイル名、ファイルフォーマットを拡張子とする Hive スタイルのパーティションディレクトリを生成します。デフォルトは WILDCARD です。
  • partition_columns_in_data_file - HIVE パーティション戦略でのみ使用されます。データファイル内にパーティション列が書き込まれていることを ClickHouse が想定すべきかどうかを指定します。デフォルトは false です。
  • storage_class_name - オプション: STANDARD または INTELLIGENT_TIERINGAWS S3 Intelligent Tiering を指定できます。

データキャッシュ

S3 テーブルエンジンはローカルディスク上でのデータキャッシュをサポートします。 ファイルシステムキャッシュの設定オプションと使用方法については、このセクションを参照してください。 キャッシュはストレージオブジェクトのパスと ETag に基づいて行われるので、ClickHouse は古いキャッシュバージョンを読み取りません。

キャッシュを有効にするには、設定 filesystem_cache_name = '<name>'enable_filesystem_cache = 1 を使用します。

SELECT *
FROM s3('http://minio:10000/clickhouse//test_3.csv', 'minioadmin', 'minioadminpassword', 'CSV')
SETTINGS filesystem_cache_name = 'cache_for_s3', enable_filesystem_cache = 1;

設定ファイルでキャッシュを定義する方法は 2 つあります。

  1. ClickHouse の設定ファイルに次のセクションを追加します:
<clickhouse>
    <filesystem_caches>
        <cache_for_s3>
            <path>キャッシュディレクトリへのパス</path>
            <max_size>10Gi</max_size>
        </cache_for_s3>
    </filesystem_caches>
</clickhouse>
  1. ClickHouse の storage_configuration セクションで設定されたキャッシュ構成(およびそれに伴うキャッシュストレージ)を再利用します。詳しくはこちらを参照してください。

PARTITION BY

PARTITION BY — 省略可能です。ほとんどの場合、パーティションキーは不要であり、必要な場合でも月単位より細かいパーティションキーが求められることはほぼありません。パーティション分割は(ORDER BY 式とは対照的に)クエリを高速化しません。過度に細かいパーティション分割は避けてください。データをクライアント識別子や名前でパーティション分割しないでください(代わりに、ORDER BY 式の最初の列としてクライアント識別子または名前を指定してください)。

月単位でパーティション分割するには、date_column が型 Date の日付を持つ列であるとき、toYYYYMM(date_column) 式を使用します。ここでのパーティション名は "YYYYMM" 形式になります。

パーティション戦略

WILDCARD(デフォルト): ファイルパス内の {_partition_id} ワイルドカードを実際のパーティションキーに置き換えます。読み取りはサポートされていません。

HIVE は読み書きのために Hive スタイルのパーティショニングを実装しています。読み取りは再帰的なグロブパターンを使って行われ、SELECT * FROM s3('table_root/**.parquet') と同等です。 書き込みでは、次の形式でファイルを生成します: <prefix>/<key1=val1/key2=val2...>/<snowflakeid>.<toLower(file_format)>

注意: HIVE パーティション方式を使用する場合、use_hive_partitioning 設定は効果はありません。

HIVE パーティション方式の例:

arthur :) CREATE TABLE t_03363_parquet (year UInt16, country String, counter UInt8)
ENGINE = S3(s3_conn, filename = 't_03363_parquet', format = Parquet, partition_strategy='hive')
PARTITION BY (year, country);

arthur :) INSERT INTO t_03363_parquet VALUES
    (2022, 'USA', 1),
    (2022, 'Canada', 2),
    (2023, 'USA', 3),
    (2023, 'Mexico', 4),
    (2024, 'France', 5),
    (2024, 'Germany', 6),
    (2024, 'Germany', 7),
    (1999, 'Brazil', 8),
    (2100, 'Japan', 9),
    (2024, 'CN', 10),
    (2025, '', 11);

arthur :) select _path, * from t_03363_parquet;

    ┌─_path──────────────────────────────────────────────────────────────────────┬─year─┬─country─┬─counter─┐
 1. │ test/t_03363_parquet/year=2100/country=Japan/7329604473272971264.parquet   │ 2100 │ Japan   │       9 │
 2. │ test/t_03363_parquet/year=2024/country=France/7329604473323302912.parquet  │ 2024 │ France  │       5 │
 3. │ test/t_03363_parquet/year=2022/country=Canada/7329604473314914304.parquet  │ 2022 │ Canada  │       2 │
 4. │ test/t_03363_parquet/year=1999/country=Brazil/7329604473289748480.parquet  │ 1999 │ Brazil  │       8 │
 5. │ test/t_03363_parquet/year=2023/country=Mexico/7329604473293942784.parquet  │ 2023 │ Mexico  │       4 │
 6. │ test/t_03363_parquet/year=2023/country=USA/7329604473319108608.parquet     │ 2023 │ USA     │       3 │
 7. │ test/t_03363_parquet/year=2025/country=/7329604473327497216.parquet        │ 2025 │         │      11 │
 8. │ test/t_03363_parquet/year=2024/country=CN/7329604473310720000.parquet      │ 2024 │ CN      │      10 │
 9. │ test/t_03363_parquet/year=2022/country=USA/7329604473298137088.parquet     │ 2022 │ USA     │       1 │
10. │ test/t_03363_parquet/year=2024/country=Germany/7329604473306525696.parquet │ 2024 │ Germany │       6 │
11. │ test/t_03363_parquet/year=2024/country=Germany/7329604473306525696.parquet │ 2024 │ Germany │       7 │
    └────────────────────────────────────────────────────────────────────────────┴──────┴─────────┴─────────┘

パーティション化されたデータのクエリ実行

この例では、ClickHouse と MinIO を統合した docker compose recipe を使用します。エンドポイントと認証情報の値を差し替えることで、S3 を使って同じクエリを再現できます。

ENGINE 設定内の S3 エンドポイントでは、S3 オブジェクト(ファイル名)の一部としてパラメータトークン {_partition_id} を使用しており、SELECT クエリはそれによって生成されるオブジェクト名(例: test_3.csv)を対象に実行されます。

注記

例で示したように、パーティション分割された S3 テーブルに対するクエリは 現時点では直接はサポートされていませんが、S3 テーブル関数を使って 個々のパーティションにクエリを実行することで実現できます。

S3 にパーティション分割されたデータを書き込む主なユースケースは、 そのデータを別の ClickHouse システムに転送できるようにすることです (たとえば、オンプレミス環境から ClickHouse Cloud へ移行する場合など)。 ClickHouse のデータセットは非常に大きくなることが多く、またネットワークの 信頼性が必ずしも完璧ではないため、データセットをサブセットに分割して 転送する、すなわちパーティション分割して書き込むのが理にかなっています。

テーブルを作成する

CREATE TABLE p
(
    `column1` UInt32,
    `column2` UInt32,
    `column3` UInt32
)
ENGINE = S3(
-- highlight-next-line
           'http://minio:10000/clickhouse//test_{_partition_id}.csv',
           'minioadmin',
           'minioadminpassword',
           'CSV')
PARTITION BY column3

データを挿入する

INSERT INTO p VALUES (1, 2, 3), (3, 2, 1), (78, 43, 45)

パーティション 3 からの選択

ヒント

このクエリは S3 テーブル関数を使用します。

SELECT *
FROM s3('http://minio:10000/clickhouse//test_3.csv', 'minioadmin', 'minioadminpassword', 'CSV')
┌─c1─┬─c2─┬─c3─┐
│  1 │  2 │  3 │
└────┴────┴────┘

パーティション1からの SELECT

SELECT *
FROM s3('http://minio:10000/clickhouse//test_1.csv', 'minioadmin', 'minioadminpassword', 'CSV')
┌─c1─┬─c2─┬─c3─┐
│  3 │  2 │  1 │
└────┴────┴────┘

パーティション45からのSELECT

SELECT *
FROM s3('http://minio:10000/clickhouse//test_45.csv', 'minioadmin', 'minioadminpassword', 'CSV')
┌─c1─┬─c2─┬─c3─┐
│ 78 │ 43 │ 45 │
└────┴────┴────┘

制限事項

つい Select * from p を実行したくなるかもしれませんが、上述のとおりこのクエリは失敗します。前述のクエリを使用してください。

SELECT * FROM p
サーバーから例外を受信しました (バージョン 23.4.1):
Code: 48. DB::Exception: localhost:9000 から受信しました。DB::Exception: パーティション化されたS3ストレージからの読み取りはまだ実装されていません。(NOT_IMPLEMENTED)

データの挿入

行は新しいファイルにのみ挿入できる点に注意してください。マージ処理やファイル分割処理は行われません。いったんファイルが書き込まれると、その後の挿入は失敗します。これを回避するには、s3_truncate_on_insert および s3_create_new_file_on_insert の設定を使用できます。詳細はこちらを参照してください。

仮想列

  • _path — ファイルのパス。型: LowCardinality(String)
  • _file — ファイル名。型: LowCardinality(String)
  • _size — ファイルのサイズ(バイト単位)。型: Nullable(UInt64)。サイズが不明な場合、値は NULL です。
  • _time — ファイルの最終更新時刻。型: Nullable(DateTime)。時刻が不明な場合、値は NULL です。
  • _etag — ファイルの ETag。型: LowCardinality(String)。ETag が不明な場合、値は NULL です。
  • _tags — ファイルのタグ。型: Map(String, String)。タグが存在しない場合、値は空のマップ `'。

仮想列の詳細については こちら を参照してください。

実装の詳細

  • 読み取りと書き込みは並行して実行できます

  • サポートされていない項目:

    • ALTERSELECT...SAMPLE の操作
    • インデックス
    • Zero-copy レプリケーションは実行可能ですが、サポート対象外です。
    Zero-copy レプリケーションは本番利用にはまだ準備ができていません

    Zero-copy レプリケーションは ClickHouse バージョン 22.8 以降ではデフォルトで無効化されています。この機能は本番環境での使用は推奨されません。

パスのワイルドカード

path 引数では、bash 形式のワイルドカードを使用して複数ファイルを指定できます。処理対象となるには、ファイルが存在し、パスパターン全体に一致している必要があります。ファイルの一覧は SELECT 実行時に決定されます(CREATE 時点ではありません)。

  • */ を除く任意の文字列(空文字列も含む)に 0 文字以上マッチします。
  • **/ を含む任意の文字列(空文字列も含む)に 0 文字以上マッチします。
  • ? — 任意の 1 文字にマッチします。
  • {some_string,another_string,yet_another_one} — 文字列 'some_string', 'another_string', 'yet_another_one' のいずれか 1 つにマッチします。
  • {N..M} — N から M までの範囲(両端を含む)の任意の数値にマッチします。N と M には先頭ゼロを含めることができます(例: 000..078)。

{} を使った構文は、remote テーブル関数と同様です。

注記

ファイル一覧に先頭ゼロ付きの数値範囲が含まれる場合は、各桁ごとに波括弧を用いた構文を使うか、? を使用してください。

ワイルドカードを用いた例 1

file-000.csv, file-001.csv, ... , file-999.csv という名前のファイルを対象とするテーブルを作成します:

CREATE TABLE big_table (name String, value UInt32)
    ENGINE = S3('https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/my_folder/file-{000..999}.csv', 'CSV');

ワイルドカードを用いた例 2

S3 上に、次の URI を持つ CSV 形式のファイルが複数あるとします:

これら 6 つのファイルすべてを含むテーブルを作成する方法はいくつかあります:

  1. ファイル名の末尾の範囲を指定する:
CREATE TABLE table_with_range (name String, value UInt32)
    ENGINE = S3('https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/{some,another}_folder/some_file_{1..3}', 'CSV');
  1. some_file_ というプレフィックスが付いたファイルをすべて取り出します(両方のフォルダに、そのようなプレフィックスが付いた余分なファイルが存在しないことを前提とします):
CREATE TABLE table_with_question_mark (name String, value UInt32)
    ENGINE = S3('https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/{some,another}_folder/some_file_?', 'CSV');
  1. 両方のフォルダ内にあるすべてのファイルを取得します(各ファイルは、クエリで説明した形式とスキーマに準拠している必要があります):
CREATE TABLE table_with_asterisk (name String, value UInt32)
    ENGINE = S3('https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/{some,another}_folder/*', 'CSV');

ストレージ設定

  • s3_truncate_on_insert - 挿入前にファイルを切り詰められるようにします。デフォルトでは無効です。
  • s3_create_new_file_on_insert - フォーマットにサフィックスが付いている場合、挿入のたびに新しいファイルを作成できるようにします。デフォルトでは無効です。
  • s3_skip_empty_files - 読み取り時に空のファイルをスキップできるようにします。デフォルトでは有効です。

S3 関連の設定

以下の設定は、クエリ実行前に指定するか、設定ファイルに記述できます。

  • s3_max_single_part_upload_size — S3 への単一パートアップロードでアップロードするオブジェクトの最大サイズ。デフォルト値は 32Mb
  • s3_min_upload_part_sizeS3 Multipart upload によるマルチパートアップロード時にアップロードするパートの最小サイズ。デフォルト値は 16Mb
  • s3_max_redirects — 許可される S3 リダイレクトのホップ数の上限。デフォルト値は 10
  • s3_single_read_retries — 単一の読み取り処理における最大再試行回数。デフォルト値は 4
  • s3_max_put_rps — レート制限(スロットリング)が行われる前の 1 秒あたりの最大 PUT リクエスト数。デフォルト値は 0(無制限)。
  • s3_max_put_burst — 1 秒あたりの上限に達する前に同時に発行できるリクエストの最大数。デフォルト値(0 の場合)は s3_max_put_rps と同じ。
  • s3_max_get_rps — レート制限(スロットリング)が行われる前の 1 秒あたりの最大 GET リクエスト数。デフォルト値は 0(無制限)。
  • s3_max_get_burst — 1 秒あたりの上限に達する前に同時に発行できるリクエストの最大数。デフォルト値(0 の場合)は s3_max_get_rps と同じ。
  • s3_upload_part_size_multiply_factor - 単一の書き込みから S3 に対して s3_multiply_parts_count_threshold 個のパートがアップロードされるたびに、s3_min_upload_part_size にこの係数を掛けます。デフォルト値は 2
  • s3_upload_part_size_multiply_parts_count_threshold - この数のパートが S3 にアップロードされるたびに、s3_min_upload_part_sizes3_upload_part_size_multiply_factor 倍になります。デフォルト値は 500
  • s3_max_inflight_parts_for_one_file - 1 つのオブジェクトに対して同時に実行できる PUT リクエスト数を制限します。この数は制限しておく必要があります。値 0 は無制限を意味します。デフォルト値は 20。各インフライト中のパートは、最初の s3_upload_part_size_multiply_factor 個のパートについては s3_min_upload_part_size サイズのバッファを持ち、ファイルが十分に大きい場合にはそれより大きくなります。upload_part_size_multiply_factor を参照してください。デフォルト設定では、1 つのアップロード済みファイルは、サイズが 8G 未満のファイルであれば最大でも 320Mb しか消費しません。より大きなファイルでは消費量は増加します。

セキュリティ上の考慮事項: 悪意あるユーザーが任意の S3 URL を指定できる場合、SSRF 攻撃を回避するために s3_max_redirects を 0 に設定する必要があります。あるいは、サーバー設定で remote_host_filter を指定する必要があります。

エンドポイント単位の設定

次の設定は、特定のエンドポイント用に設定ファイル内で指定できます(URL のプレフィックスの完全一致で判定されます)。

  • endpoint — エンドポイントのプレフィックスを指定します。必須です。
  • access_key_idsecret_access_key — 指定したエンドポイントで使用する認証情報を指定します。任意です。
  • use_environment_credentialstrue に設定すると、S3 クライアントは環境変数および Amazon EC2 のメタデータから、そのエンドポイント用の認証情報を取得しようとします。任意で、デフォルト値は false です。
  • region — S3 リージョン名を指定します。任意です。
  • use_insecure_imds_requesttrue に設定すると、S3 クライアントは Amazon EC2 メタデータから認証情報を取得する際に、非セキュアな IMDS リクエストを使用します。任意で、デフォルト値は false です。
  • expiration_window_seconds — 有効期限付き認証情報が失効しているかを確認するための猶予期間(グレースピリオド)です。任意で、デフォルト値は 120 です。
  • no_sign_request - すべての認証情報を無視し、リクエストに署名しません。公開バケットにアクセスする場合に便利です。
  • header — 指定した HTTP ヘッダーを、そのエンドポイントへのリクエストに追加します。任意で、複数回指定できます。
  • access_header - 他のソースからの認証情報が存在しない場合に限り、指定した HTTP ヘッダーをそのエンドポイントへのリクエストに追加します。
  • server_side_encryption_customer_key_base64 — 指定した場合、SSE-C 暗号化された S3 オブジェクトへアクセスするために必要なヘッダーが設定されます。任意です。
  • server_side_encryption_kms_key_id - 指定した場合、SSE-KMS 暗号化 された S3 オブジェクトへアクセスするために必要なヘッダーが設定されます。空文字列を指定した場合は、AWS 管理の S3 キーが使用されます。任意です。
  • server_side_encryption_kms_encryption_context - server_side_encryption_kms_key_id と併せて指定した場合、指定した暗号化コンテキストのヘッダーが SSE-KMS 用に設定されます。任意です。
  • server_side_encryption_kms_bucket_key_enabled - server_side_encryption_kms_key_id と併せて指定した場合、SSE-KMS 用に S3 バケットキーを有効化するヘッダーが設定されます。任意で、true または false を指定でき、デフォルトは未設定(バケットレベルの設定に従います)です。
  • max_single_read_retries — 単一の読み取り処理中に試行される最大回数です。デフォルト値は 4 です。任意です。
  • max_put_rps, max_put_burst, max_get_rps および max_get_burst - 特定のエンドポイントで、クエリ単位ではなく使用するレート制限(スロットリング)設定です(上記の説明を参照)。任意です。

例:

<s3>
    <endpoint-name>
        <endpoint>https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/</endpoint>
        <!-- <access_key_id>ACCESS_KEY_ID</access_key_id> -->
        <!-- <secret_access_key>SECRET_ACCESS_KEY</secret_access_key> -->
        <!-- <region>us-west-1</region> -->
        <!-- <use_environment_credentials>false</use_environment_credentials> -->
        <!-- <use_insecure_imds_request>false</use_insecure_imds_request> -->
        <!-- <expiration_window_seconds>120</expiration_window_seconds> -->
        <!-- <no_sign_request>false</no_sign_request> -->
        <!-- <header>Authorization: Bearer SOME-TOKEN</header> -->
        <!-- <server_side_encryption_customer_key_base64>BASE64-ENCODED-KEY</server_side_encryption_customer_key_base64> -->
        <!-- <server_side_encryption_kms_key_id>KMS_KEY_ID</server_side_encryption_kms_key_id> -->
        <!-- <server_side_encryption_kms_encryption_context>KMS_ENCRYPTION_CONTEXT</server_side_encryption_kms_encryption_context> -->
        <!-- <server_side_encryption_kms_bucket_key_enabled>true</server_side_encryption_kms_bucket_key_enabled> -->
        <!-- <max_single_read_retries>4</max_single_read_retries> -->
    </endpoint-name>
</s3>

アーカイブの操作

S3 上に、次の URI を持つ複数のアーカイブファイルがあるとします:

これらのアーカイブからデータを抽出することは、:: を使用することで可能です。グロブは、URL の部分と、アーカイブ内のファイル名を指定する :: の後ろの部分の両方で使用できます。

SELECT *
FROM s3(
   'https://s3-us-west-1.amazonaws.com/umbrella-static/top-1m-2018-01-1{0..2}.csv.zip :: *.csv'
);
注記

ClickHouse は次の 3 種類のアーカイブ形式をサポートしています: ZIP TAR 7Z ZIP および TAR アーカイブはサポートされている任意のストレージロケーションからアクセスできますが、7Z アーカイブは ClickHouse がインストールされているローカルファイルシステムからのみ読み取り可能です。

公開バケットへのアクセス

ClickHouse は、さまざまな種類のソースから認証情報を取得しようとします。 そのため、公開されている一部のバケットにアクセスする際に問題が発生し、クライアントが 403 エラーコードを返すことがあります。 この問題は、NOSIGN キーワードを使用してクライアントにすべての認証情報を無視させ、リクエストへ署名させないように強制することで回避できます。

CREATE TABLE big_table (name String, value UInt32)
    ENGINE = S3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/aapl_stock.csv', NOSIGN, 'CSVWithNames');

パフォーマンスの最適化

s3 関数のパフォーマンス最適化の詳細については、詳細ガイドを参照してください。

関連項目