S3 テーブルエンジン
このエンジンは 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 BY expr]
[SETTINGS ...]
エンジンのパラメータ
path— ファイルへのパスを含むバケットURL。以下のワイルドカードを読み取り専用モードでサポートします:*,**,?,{abc,def}および{N..M}(N,Mは数値、'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。このパラメータはオプションで、デフォルトではファイル拡張子によって圧縮形式を自動的に検出します。
データキャッシュ
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つあります。
- 次のセクションをClickHouseの構成ファイルに追加します:
<clickhouse>
<filesystem_caches>
<cache_for_s3>
<path>キャッシュディレクトリへのパス</path>
<max_size>10Gi</max_size>
</cache_for_s3>
</filesystem_caches>
</clickhouse>
- ClickHouseの
storage_configurationセクションからキャッシュ構成を再利用し、キャッシュストレージを使用します。詳細はこちらをご覧ください。
PARTITION BY
PARTITION BY — オプションです。ほとんどの場合、分割キーは必要ありませんが、必要な場合でも通常は1ヶ月単位より細かい分割キーは必要ありません。パーティショニングはクエリの高速化に寄与しません(ORDER BY 表現とは対照的に)。決して細かすぎるパーティショニングを使ってはいけません。クライアントIDや名前でデータを分割するのではなく、クライアントIDや名前を ORDER BY 表現の最初のカラムにするべきです。
月単位で分割するには、toYYYYMM(date_column) 式を使用します。ここで date_column は Date 型の日付を持つカラムです。ここでのパーティション名は "YYYYMM" フォーマットです。
パーティションされたデータのクエリ
この例は、ClickHouseとMinIOを統合するドッカーコンポーズレシピを使用します。同じクエリを使用して、エンドポイントや認証値を置き換えることで、S3を利用することができます。
ENGINE 構成のS3エンドポイントには、S3オブジェクト(ファイル名)の一部として _partition_id パラメータトークンを使用し、それらの結果オブジェクト名(例:test_3.csv)を選択します。
例に示されているように、現在のところパーティション化されたS3テーブルからのクエリは直接サポートされていませんが、S3テーブル関数を使用して個々のパーティションをクエリすることで達成できます。
主なユースケースは、S3でパーティション化されたデータを書き込むことにより、データを他の ClickHouseシステムに転送すること(例えば、オンプレミスシステムからClickHouse Cloudに移行)です。ClickHouseのデータセットは非常に大きいことが多いため、ネットワークの信頼性が欠けることもあるので、データセットを部分ごとに転送するのが合理的です。したがって、パーティション化された書き込みが役立ちます。
テーブルの作成
CREATE TABLE p
(
`column1` UInt32,
`column2` UInt32,
`column3` UInt32
)
ENGINE = S3(
'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 *
FROM s3('http://minio:10000/clickhouse//test_1.csv', 'minioadmin', 'minioadminpassword', 'CSV')
┌─c1─┬─c2─┬─c3─┐
│ 3 │ 2 │ 1 │
└────┴────┴────┘
パーティション 45 からの選択
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
Received exception from server (version 23.4.1):
Code: 48. DB::Exception: Received from localhost:9000. DB::Exception: Reading from a partitioned S3 storage is not implemented yet. (NOT_IMPLEMENTED)
仮想カラム
_path— ファイルへのパス。型:LowCardinalty(String)。_file— ファイル名。型:LowCardinalty(String)。_size— ファイルのバイト単位のサイズ。型:Nullable(UInt64)。サイズが不明な場合、値はNULL。_time— ファイルの最終変更時間。型:Nullable(DateTime)。時間が不明な場合、値はNULL。_etag— ファイルのETag。型:LowCardinalty(String)。ETagが不明な場合、値はNULL。
仮想カラムについての詳細はこちらをご覧ください。
実装の詳細
読み書きは並行して行うことが可能
サポートされていません:
ALTERおよびSELECT...SAMPLE操作。- インデックス。
- ゼロコピーのレプリケーションは可能ですが、サポートされていません。
Noteプロダクションにはゼロコピーのレプリケーションは推奨されません ゼロコピーのレプリケーションはClickHouseバージョン22.8以降でデフォルトで無効になっています。この機能はプロダクション環境での使用は推奨されません。
パス内のワイルドカード
path 引数はbashのようなワイルドカードを用いて複数のファイルを指定できます。処理されるためには、ファイルが存在し、パスパターン全体に一致する必要があります。ファイルのリストは SELECT 時に決定されます(CREATE の時点ではありません)。
*—/を除く任意の数の任意の文字を空文字列も含めて代替します。**—/を含む任意の数の任意の文字を空文字列も含めて代替します。?— 任意の単一の文字を代替します。{some_string,another_string,yet_another_one}— 文字列'some_string', 'another_string', 'yet_another_one'のいずれかを代替します。{N..M}— 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にはCSVフォーマットの以下のURIを持ついくつかのファイルがあるとします:
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/some_folder/some_file_1.csv'
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/some_folder/some_file_2.csv'
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/some_folder/some_file_3.csv'
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/another_folder/some_file_1.csv'
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/another_folder/some_file_2.csv'
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/another_folder/some_file_3.csv'
これら6つのファイルを構成するテーブルを作成する方法は以下の通りです:
- ファイルの接尾辞の範囲を指定します:
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');
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');
- 両方のフォルダ内のすべてのファイルを取得します(すべてのファイルがクエリで説明されているフォーマットとスキーマを満たす必要があります):
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_size— S3マルチパートアップロード中にアップロードするパートの最小サイズ。デフォルト値は16Mb。s3_max_redirects— 許可されるS3リダイレクトホップの最大数。デフォルト値は10。s3_single_read_retries— 単一の読み取り中の試行最大数。デフォルト値は4。s3_max_put_rps— スロットリング前の1秒あたりの最大PUTリクエスト数。デフォルト値は0(無制限)。s3_max_put_burst— 秒単位のリクエスト制限に達する前に同時に発行できる最大リクエスト数。デフォルトでは (0値)s3_max_put_rpsに等しい。s3_max_get_rps— スロットリング前の1秒あたりの最大GETリクエスト数。デフォルト値は0(無制限)。s3_max_get_burst— 秒単位のGETリクエスト制限に達する前に同時に発行できる最大リクエスト数。デフォルトでは (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_sizeはs3_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を参照してください。デフォルト設定で、アップロードされるファイルは8G未満の場合は320Mb以上を消費しません。消費はより大きなファイルにはさらに大きくなります。
セキュリティの考慮点: 任意のS3 URLを指定可能な悪意のあるユーザーがいた場合、s3_max_redirects をゼロに設定して SSRF 攻撃を回避する必要があります。または、サーバー構成で remote_host_filter を指定する必要があります。
エンドポイントベースの設定
以下の設定は、特定のエンドポイント(URLの正確なプレフィックスと一致する)に対して構成ファイルで指定できます:
endpoint— エンドポイントのプレフィックスを指定します。必須です。access_key_idとsecret_access_key— 特定のエンドポイントに使用するクレデンシャルを指定します。任意です。use_environment_credentials—trueに設定されている場合、S3クライアントは環境変数と Amazon EC2 メタデータからクレデンシャルを取得しようとします。任意です。デフォルト値はfalse。region— S3リージョン名を指定します。任意です。use_insecure_imds_request—trueに設定されている場合、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の複数のアーカイブファイルがあるとします:
- 'https://s3-us-west-1.amazonaws.com/umbrella-static/top-1m-2018-01-10.csv.zip'
- 'https://s3-us-west-1.amazonaws.com/umbrella-static/top-1m-2018-01-11.csv.zip'
- 'https://s3-us-west-1.amazonaws.com/umbrella-static/top-1m-2018-01-12.csv.zip'
これらのアーカイブからデータを抽出することが :: を使用して可能です。グロブは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 関数のパフォーマンス最適化に関する詳細は詳細ガイドをご覧ください。