CREATE TABLE
新しいテーブルを作成します。このクエリは、ユースケースに応じてさまざまな構文が利用できます。
デフォルトでは、テーブルは現在のサーバー上にのみ作成されます。分散 DDL クエリは ON CLUSTER 句として実装されており、別途説明されています。
構文形式
明示的なスキーマ指定
db データベース、もしくは db が設定されていない場合は現在のデータベースに、括弧内で指定された構造と engine エンジンを持つ table_name という名前のテーブルを作成します。
テーブルの構造は、列定義、セカンダリインデックス、および制約の一覧です。エンジンが primary key をサポートしている場合、テーブルエンジンのパラメータとして指定します。
最も単純な場合、列定義は name type です。例: RegionID UInt32。
デフォルト値用の式を定義することもできます(下記参照)。
必要に応じて、1 つ以上のキー式を用いて primary key を指定できます。
列およびテーブルにコメントを追加できます。
他のテーブルと同様のスキーマを使用する場合
別のテーブルと同じ構造のテーブルを作成します。テーブルに別のエンジンを指定できます。エンジンを指定しない場合は、db2.name2 テーブルと同じエンジンが使用されます。
別のテーブルからスキーマとデータをクローンする場合
別のテーブルと同じ構造を持つテーブルを作成します。テーブルには異なるエンジンを指定できます。エンジンが指定されていない場合、db2.name2 テーブルと同じエンジンが使用されます。新しいテーブルが作成された後、db2.name2 のすべてのパーティションがそのテーブルにアタッチされます。言い換えると、db2.name2 のデータは作成時に db.table_name にクローンされます。このクエリは次のものと等価です:
テーブル関数から
指定したテーブル関数と同じ結果になるテーブルを作成します。作成されたテーブルは、指定した対応するテーブル関数と同様に動作します。
SELECT クエリから
SELECT クエリの結果と同じ構造を持つテーブルを、engine エンジンを使用して作成し、SELECT で得られたデータを挿入します。列の定義を明示的に指定することもできます。
テーブルがすでに存在していて IF NOT EXISTS が指定されている場合、このクエリは何も行いません。
クエリの ENGINE 句の後には、他の句を続けて指定することができます。テーブルの作成方法についての詳細なドキュメントは、table engines の説明を参照してください。
例
クエリ:
結果:
NULL または NOT NULL 修飾子
列定義におけるデータ型の後ろに付ける NULL および NOT NULL 修飾子は、その列を Nullable 型にできるかどうかを指定します。
型が Nullable でない場合に NULL が指定されると、その型は Nullable として扱われます。NOT NULL が指定されると、Nullable にはなりません。例えば、INT NULL は Nullable(INT) と同じ意味になります。型がすでに Nullable であり、そこに NULL または NOT NULL 修飾子が指定された場合は、例外がスローされます。
data_type_default_nullable 設定も参照してください。
デフォルト値
カラム定義では、DEFAULT expr、MATERIALIZED expr、ALIAS expr の形式でデフォルト値の式を指定できます。例: URLDomain String DEFAULT domain(URL)。
式 expr は省略可能です。省略された場合、カラム型を明示的に指定しなければならず、デフォルト値は数値カラムでは 0、文字列カラムでは ''(空文字列)、配列カラムでは [](空配列)、日付カラムでは 1970-01-01、Nullable カラムでは NULL になります。
デフォルト値を持つカラムについては、カラム型を省略することができ、その場合は expr の型から推論されます。例えば、カラム EventDate DEFAULT toDate(EventTime) の型は Date 型になります。
データ型とデフォルト値の式が両方指定されている場合、式を指定された型に変換する暗黙の型変換関数が挿入されます。例: Hits UInt32 DEFAULT 0 は内部的には Hits UInt32 DEFAULT toUInt32(0) として表現されます。
デフォルト値の式 expr では、任意のテーブルカラムおよび定数を参照できます。ClickHouse は、テーブル構造の変更によって式の計算にループが導入されないことを検証します。INSERT 時には、式が解決可能であること、つまり式の計算に必要となるすべてのカラムが指定されていることを確認します。
DEFAULT
DEFAULT expr
通常のデフォルト値です。INSERT クエリでこのカラムの値が指定されなかった場合、expr から計算されます。
例:
MATERIALIZED
MATERIALIZED expr
マテリアライズド式。行が挿入されるとき、これらの列の値は指定されたマテリアライズド式に従って自動的に計算されます。INSERT 時に値を明示的に指定することはできません。
また、この型のデフォルト値列は SELECT * の結果には含まれません。これは、SELECT * の結果を常に INSERT を使ってテーブルにそのまま挿入し直せる、という不変条件を維持するためです。この挙動は、設定 asterisk_include_materialized_columns によって無効化できます。
例:
EPHEMERAL
EPHEMERAL [expr]
エフェメラル列。 この型の列はテーブルに保存されず、そこから SELECT することはできません。 エフェメラル列の唯一の目的は、それを利用して他の列のデフォルト値式を構築することです。
明示的に列を指定しない INSERT では、この型の列はスキップされます。 これは、SELECT * の結果を常に INSERT を使ってテーブルに挿入し直せるというインバリアントを維持するためです。
例:
Row 1: ────── id: 1 hexed: Z�� hex(hexed): 5A90B714
プライマリキー
テーブル作成時にプライマリキーを定義できます。プライマリキーは次の 2 通りの方法で指定できます。
- 列リスト内で指定する
- 列リスト外
1 つのクエリで両方の方法を併用することはできません。
制約
カラムの説明に加えて、制約を定義することもできます。
CONSTRAINT
boolean_expr_1 には任意のブール式を指定できます。テーブルに制約が定義されている場合、INSERT クエリで挿入される各行に対して、それぞれの制約が検証されます。いずれかの制約が満たされない場合、サーバーは制約名と検証に使用された式を含む例外をスローします。
大量の制約を追加すると、大規模な INSERT クエリのパフォーマンスに悪影響を与える可能性があります。
ASSUME
ASSUME 句は、常に真であると仮定されるテーブル上の CONSTRAINT を定義するために使用されます。この制約は、その後オプティマイザによって SQL クエリのパフォーマンスを向上させるために利用できます。
次の例では、users_a テーブルを作成する際に ASSUME CONSTRAINT を使用しています。
ここで、ASSUME CONSTRAINT は、length(name) 関数が常に name_len カラムの値と等しいと仮定するために使用されています。これは、クエリ内で length(name) が呼び出されるたびに、ClickHouse がそれを name_len に置き換えることができることを意味します。length() 関数の呼び出しを避けられるため、その方が高速になるはずです。
次に、クエリ SELECT name FROM users_a WHERE length(name) < 5; を実行するとき、ClickHouse は ASSUME CONSTRAINT によって、これを SELECT name FROM users_a WHERE name_len < 5; に最適化できます。これにより、各行について name の長さを計算する処理を避けられるため、クエリの実行が速くなる可能性があります。
ASSUME CONSTRAINT は 制約を強制しません。単にオプティマイザに対して、その制約が成り立つことを知らせるだけです。もし制約が実際には成り立たない場合、クエリ結果が不正確になる可能性があります。したがって、制約が正しいと確信できる場合にのみ ASSUME CONSTRAINT を使用すべきです。
TTL Expression
値の保持期間を定義します。MergeTree ファミリーのテーブルに対してのみ指定できます。詳細については、列およびテーブルの TTL を参照してください。
列圧縮コーデック
デフォルトでは、セルフマネージド版の ClickHouse では lz4 圧縮が、ClickHouse Cloud では zstd 圧縮が適用されます。
MergeTree エンジンファミリーでは、サーバー設定の compression セクションでデフォルトの圧縮方式を変更できます。
また、CREATE TABLE クエリ内で各列ごとに圧縮方式を定義することもできます。
Default コーデックを指定すると、デフォルトの圧縮方式を使用できます。これは実行時のさまざまな設定(およびデータの特性)に依存する場合があります。
例: value UInt64 CODEC(Default) — コーデック指定がない場合と同じです。
また、列から現在の CODEC を削除し、config.xml で定義されたデフォルトの圧縮方式を使用することもできます:
Codec はパイプラインで組み合わせることができます。たとえば CODEC(Delta, Default) のように指定します。
lz4 のような外部ユーティリティでは ClickHouse のデータベースファイルを伸長することはできません。代わりに、専用ユーティリティ clickhouse-compressor を使用してください。
次のテーブルエンジンで圧縮がサポートされています。
- MergeTree ファミリー。カラム圧縮 codec と、compression 設定によるデフォルト圧縮方式の選択をサポートします。
- Log ファミリー。デフォルトで
lz4圧縮方式を使用し、カラム圧縮 codec をサポートします。 - Set。デフォルト圧縮のみサポートします。
- Join。デフォルト圧縮のみサポートします。
ClickHouse は、汎用 codec と用途特化 codec の両方をサポートします。
汎用 Codec
NONE
NONE — 圧縮しません。
LZ4
LZ4 — デフォルトで使用されるロスレスデータ圧縮アルゴリズムです。LZ4 の高速圧縮を適用します。
LZ4HC
LZ4HC[(level)] — 圧縮レベルを指定できる LZ4 HC (High Compression) アルゴリズムです。デフォルトレベル: 9。level <= 0 を指定するとデフォルトレベルが適用されます。指定可能なレベル: [1, 12]。推奨レベル範囲: [4, 9]。
ZSTD
ZSTD[(level)] — 可変 level を持つ ZSTD 圧縮アルゴリズム です。指定可能なレベル: [1, 22]。デフォルトレベル: 1。
高い圧縮レベルは、一度圧縮しておき、そのデータを繰り返し伸長するといった非対称なシナリオで有用です。レベルを上げると圧縮率は向上しますが、CPU 使用率も増加します。
ZSTD_QAT
ZSTD_QAT[(level)] — Intel® QATlib および Intel® QAT ZSTD Plugin で実装された、レベルを指定できる ZSTD 圧縮アルゴリズム です。指定可能なレベル: [1, 12]。デフォルトレベル: 1。推奨レベル範囲: [6, 12]。いくつかの制限があります。
- ZSTD_QAT はデフォルトでは無効で、設定項目 enable_zstd_qat_codec を有効化して初めて使用できます。
- 圧縮時、ZSTD_QAT は Intel® QAT オフロードデバイス(QuickAssist Technology)の利用を試みます。そのようなデバイスが見つからない場合は、ソフトウェアによる ZSTD 圧縮にフォールバックします。
- 伸長は常にソフトウェアで実行されます。
DEFLATE_QPL
DEFLATE_QPL — Intel® Query Processing Library によって実装された Deflate 圧縮アルゴリズム です。いくつかの制限があります。
- DEFLATE_QPL はデフォルトでは無効になっており、設定 enable_deflate_qpl_codec を有効化した後にのみ使用できます。
- DEFLATE_QPL には、SSE 4.2 命令でコンパイルされた ClickHouse ビルドが必要です(デフォルトでそのようにビルドされています)。詳細は Build Clickhouse with DEFLATE_QPL を参照してください。
- DEFLATE_QPL は、システムに Intel® IAA (In-Memory Analytics Accelerator) オフロードデバイスがある場合に最も効果的に動作します。詳細は Accelerator Configuration および Benchmark with DEFLATE_QPL を参照してください。
- DEFLATE_QPL で圧縮されたデータは、SSE 4.2 を有効にしてコンパイルされた ClickHouse ノード間でのみ転送できます。
Specialized Codecs
これらのコーデックは、データの特定の特徴を利用して圧縮をより効果的にするよう設計されています。これらのコーデックの一部は自分自身ではデータを圧縮せず、汎用コーデックを用いた第 2 段階の圧縮でより高い圧縮率を得られるように、あらかじめデータを前処理します。
Delta
Delta(delta_bytes) — 生の値を、直前の値との差分で置き換える圧縮手法です。先頭の値だけは変更されません。delta_bytes は生の値の最大サイズであり、デフォルト値は sizeof(type) です。delta_bytes を引数として指定する方法は非推奨であり、将来のリリースでサポートは削除されます。Delta はデータ準備用コーデックであり、単独では使用できません。
DoubleDelta
DoubleDelta(bytes_size) — 差分の差分を計算し、それをコンパクトなバイナリ形式で書き込みます。bytes_size は Delta コーデックにおける delta_bytes と同様の意味を持ちます。bytes_size を引数として指定する方法は非推奨であり、将来のリリースでサポートは削除されます。一定のステップ幅を持つ単調増加(または単調減少)系列、例えば時系列データに対して最適な圧縮率が得られます。任意の数値型で使用できます。Gorilla TSDB で使用されているアルゴリズムを実装し、64 ビット型をサポートするように拡張しています。32 ビットのデルタに対しては、4 ビット接頭辞ではなく 5 ビット接頭辞を使用するため、1 ビット余分に使用します。詳細については、Gorilla: A Fast, Scalable, In-Memory Time Series Database の「Compressing Time Stamps」を参照してください。DoubleDelta はデータ準備用コーデックであり、単独では使用できません。
GCD
GCD() - - 列内の値の最大公約数 (GCD) を計算し、各値をその GCD で割ります。整数、Decimal、日付/時刻の列で使用できます。このコーデックは、値が GCD の倍数単位で変化(増加または減少)する列、例: 24, 28, 16, 24, 8, 24 (GCD = 4) に適しています。GCD はデータ準備用コーデックであり、単独では使用できません。
Gorilla
Gorilla(bytes_size) — 現在の浮動小数点値と直前の浮動小数点値の XOR を計算し、それをコンパクトなバイナリ形式で書き込みます。連続する値同士の差、すなわち系列の値の変化が小さい(遅い)ほど、圧縮率は高くなります。Gorilla TSDB で使用されているアルゴリズムを実装し、64 ビット型をサポートするように拡張しています。bytes_size に指定可能な値は 1, 2, 4, 8 で、デフォルト値は 1, 2, 4, 8 のいずれかと等しい場合は sizeof(type) です。それ以外の場合は 1 になります。詳細は Gorilla: A Fast, Scalable, In-Memory Time Series Database の 4.1 節を参照してください。
FPC
FPC(level, float_size) - 2種類の予測器のうち優れている方を用いて系列中の次の浮動小数点値を繰り返し予測し、その予測値と実際の値を XOR し、その結果を先頭ゼロ圧縮するコーデックです。Gorilla と同様に、ゆっくり変化する浮動小数点値の系列を保存する場合に効率的です。64ビット値(double)の場合、FPC は Gorilla より高速であり、32ビット値の場合は状況によって異なります。level に指定可能な値は 1-28 で、デフォルト値は 12 です。float_size に指定可能な値は 4, 8 で、型が Float の場合のデフォルト値は sizeof(type) です。それ以外のすべてのケースでは 4 になります。アルゴリズムの詳細な説明については High Throughput Compression of Double-Precision Floating-Point Data を参照してください。
T64
T64 — 整数データ型(Enum、Date、DateTime を含む)の値において未使用の上位ビットを切り詰める圧縮手法です。アルゴリズムの各ステップで、コーデックは 64 個の値のブロックを取り出し、それらを 64x64 ビット行列に配置して転置し、未使用ビットを切り詰め、残りをシーケンスとして返します。未使用ビットとは、この圧縮の対象となるデータ部分全体において、最大値と最小値の間で変化しないビットを指します。
DoubleDelta と Gorilla コーデックは、Gorilla TSDB でその圧縮アルゴリズムの構成要素として使用されています。Gorilla の手法は、タイムスタンプ付きのゆっくり変化する値の系列があるシナリオで効果的です。タイムスタンプは DoubleDelta コーデックで効率的に圧縮され、値は Gorilla コーデックで効率的に圧縮されます。例えば、効率的に保存されるテーブルとするには、次の構成でテーブルを作成できます。
暗号化コーデック
これらのコーデックは実際にはデータを圧縮せず、代わりにディスク上のデータを暗号化します。これらは encryption 設定で暗号化キーが指定されている場合にのみ利用可能です。暗号化されたデータは通常、有意義な形で圧縮することができないため、暗号化はコーデックパイプラインの末尾でのみ意味を持つことに注意してください。
暗号化コーデック:
AES_128_GCM_SIV
CODEC('AES-128-GCM-SIV') — RFC 8452 で定義されている GCM-SIV モードの AES-128 でデータを暗号化します。
AES-256-GCM-SIV
CODEC('AES-256-GCM-SIV') — GCM-SIV モードの AES-256 でデータを暗号化します。
これらのコーデックは固定ノンスを使用するため、暗号化は決定的(deterministic)になります。これは ReplicatedMergeTree のような重複排除エンジンと互換性がありますが、弱点もあります。同じデータブロックを 2 回暗号化すると、得られる暗号文は完全に同一になるため、ディスクを読み取れる攻撃者は、この同一性を確認できます(ただし内容そのものではなく、同一であることだけが分かります)。
「*MergeTree」ファミリーを含むほとんどのエンジンは、コーデックを適用せずにディスク上にインデックスファイルを作成します。つまり、暗号化されたカラムがインデックスされている場合、その値の平文がディスク上に現れることになります。
暗号化されたカラムに対して特定の値を指定する SELECT クエリ(WHERE 句など)を実行すると、その値が system.query_log に記録される可能性があります。必要に応じてログ記録を無効化することを検討してください。
例
圧縮が必要な場合は、明示的に指定してください。指定しない場合は、データには暗号化のみが適用されます。
例
一時テーブル
一時テーブルはレプリケートされない点に注意してください。そのため、一時テーブルに挿入されたデータが他のレプリカで利用可能であることは保証されません。一時テーブルが有用となる主なユースケースは、単一セッション中に小規模な外部データセットに対してクエリや結合を行う場合です。
ClickHouse は、次の特性を持つ一時テーブルをサポートします。
- 一時テーブルは、セッション終了時に消滅します。これは接続が失われた場合も含みます。
- エンジンが指定されていない場合、一時テーブルは Memory テーブルエンジンを使用します。また、Replicated エンジンおよび
KeeperMapエンジン以外の任意のテーブルエンジンを使用できます。 - 一時テーブルにはデータベース名を指定できません。いずれのデータベースにも属さない形で作成されます。
- すべてのクラスタサーバー上で分散 DDL クエリ(
ON CLUSTERの使用)により一時テーブルを作成することはできません。このテーブルは現在のセッション内にのみ存在します。 - 一時テーブルが他のテーブルと同じ名前を持ち、クエリでデータベースを指定せずにテーブル名のみを指定した場合、一時テーブルが使用されます。
- 分散クエリ処理において、クエリで使用される Memory エンジンの一時テーブルはリモートサーバーに渡されます。
一時テーブルを作成するには、次の構文を使用します。
ほとんどの場合、一時テーブルは手動で作成するのではなく、クエリで外部データを使用する場合や、分散 (GLOBAL) IN のために使用する場合に自動的に作成されます。詳しくは、該当するセクションを参照してください。
一時テーブルの代わりに、ENGINE = Memory を使用したテーブルを利用することもできます。
REPLACE TABLE
REPLACE ステートメントを使用すると、テーブルをアトミックに更新できます。
このステートメントは、Atomic と Replicated の各データベースエンジンでサポートされています。
これらはそれぞれ、ClickHouse および ClickHouse Cloud のデフォルトのデータベースエンジンです。
通常、テーブルから一部のデータだけを削除する必要がある場合は、
新しいテーブルを作成し、不要なデータを取得しない SELECT ステートメントで新しいテーブルにデータを投入してから、
古いテーブルを削除し、新しいテーブルにリネームします。
このアプローチは、以下の例で示されています。
上記の方法の代わりに、デフォルトのデータベースエンジンを使用している場合は REPLACE を使って同じ結果を得ることもできます。
構文
CREATE 文のすべての構文形式は、このステートメントでも使用できます。存在しないテーブルに対して REPLACE を実行するとエラーになります。
例:
- ローカル
- Cloud
次のテーブルを例にします。
REPLACE 文を使用すると、すべてのデータを消去できます。
また、REPLACE 文を使用してテーブルの構造を変更することもできます。
ClickHouse Cloud 上に次のテーブルがあるとします。
REPLACE 文を使用すると、すべてのデータを消去できます。
また、REPLACE 文を使用してテーブルの構造を変更することもできます。
COMMENT 句
テーブル作成時にコメントを追加できます。
構文
例
クエリ:
結果:
関連コンテンツ
- ブログ記事: スキーマとコーデックによる ClickHouse の最適化
- ブログ記事: ClickHouse における時系列データの取り扱い