メインコンテンツへスキップ
ClickHouse のクエリ性能を支える中核的な理由の 1 つは、効率的なデータ圧縮です。ディスク上のデータ量が少ないほど I/O オーバーヘッドを抑えられるため、クエリと insert は高速になります。ClickHouse の column-oriented アーキテクチャでは、類似したデータが自然に隣接して配置されるため、圧縮アルゴリズムや codecs によってデータサイズを大幅に削減できます。こうした圧縮の利点を最大限に引き出すには、適切な data types を慎重に選ぶことが重要です。 ClickHouse における圧縮効率は、主に ordering key、data types、codes の 3 つの要因に左右され、これらはすべて table schema で定義されます。最適な data types を選択すると、ストレージ効率とクエリ性能の両方がすぐに向上します。 いくつかのシンプルな指針で、スキーマを大きく改善できます。
  • 厳密な型を使用する: カラムには常に正しい data type を選択してください。数値フィールドや日付フィールドには、汎用的な String type ではなく、適切な数値型や日付型を使うべきです。これにより、filter や集計において正しい意味が保たれます。
  • nullable columns を避ける: Nullable なカラムは、null 値を追跡するための別カラムを維持する必要があるため、追加のオーバーヘッドが発生します。空の状態と null の状態を明示的に区別する必要がある場合にのみ Nullable を使用してください。それ以外では、通常はデフォルト値やゼロ相当の値で十分です。必要な場合を除いてこの型を避けるべき理由の詳細については、Avoid nullable Columns を参照してください。
  • 数値の精度を最小限にする: 想定されるデータ範囲を収容できる範囲で、ビット幅が最小の数値型を選択してください。たとえば、負の値が不要で、範囲が 0–65535 に収まる場合は、Int32 より UInt16 を選択します
  • 日付と時刻の精度を最適化する: クエリ要件を満たす範囲で、できるだけ粒度の粗い日付型または日時型を選択してください。日付のみのフィールドには Date または Date32 を使用し、ミリ秒以下の精度が不可欠でない限り、DateTime64 ではなく DateTime を優先してください。
  • LowCardinality と特化型を活用する: 一意な値が概ね 10,000 未満のカラムでは、LowCardinality 型を使用すると、dictionary encoding によってストレージを大幅に削減できます。同様に、FixedString はカラム値が厳密に固定長の文字列である場合 (たとえば国コードや通貨コード) にのみ使用し、取り得る値の集合が有限なカラムには Enum 型を使うことで、効率的な保存と組み込みのデータ検証を実現できます。
  • データ検証のための Enums: Enum 型は、列挙型を効率的にエンコードするために使用できます。Enums は、格納する必要がある一意な値の数に応じて、8 ビットまたは 16 ビットのいずれかになります。insert time の検証 (宣言されていない値は拒否されます) が必要な場合や、Enum 値の自然な順序を活用するクエリを実行したい場合は、これを検討してください。たとえば、ユーザーの応答を含むフィードバックカラムに Enum(’:(’ = 1, ’:|’ = 2, ’:)’ = 3) を使うケースが考えられます。

ClickHouse には、型の最適化を容易にする組み込みツールが用意されています。たとえば、スキーマ推論によって初期の型を自動的に判別できます。Parquet フォーマットで一般公開されている Stack Overflow データセットを考えてみましょう。DESCRIBE コマンドでシンプルなスキーマ推論を実行すると、最適化前の初期スキーマを取得できます。
デフォルトでは、ClickHouse はこれらを対応する Nullable 型として扱います。これは、スキーマが行の一部のサンプルのみに基づいているためです。
以下では、stackoverflow/parquet/posts フォルダ内のすべてのファイルを読み込むために、glob パターン *.parquet を使用します。
posts テーブルに初期のシンプルなルールを適用すると、各カラムに最適な型を特定できます。
ヒントカラムの型を見極めるには、その数値の範囲と一意の値の数を把握することが重要です。すべてのカラムの値の範囲と異なる値の数を調べるには、シンプルなクエリ SELECT * APPLY min, * APPLY max, * APPLY uniq FROM table FORMAT Vertical を使用できます。ただし、これはコストが高くなる可能性があるため、より小さいデータのサブセットに対して実行することを推奨します。
これにより、型の観点では次のように最適化されたスキーマが得られます。

Nullable 型のカラムを避ける

Nullable カラム (例: Nullable(String)) は、別途 UInt8 型のカラムを作成します。ユーザーが Nullable カラムを扱うたびに、この追加カラムも毎回処理する必要があります。その結果、追加のストレージ容量が必要になり、ほとんどの場合はパフォーマンスに悪影響を及ぼします。 Nullable カラムを避けるには、そのカラムにデフォルト値を設定することを検討してください。たとえば、次のようにする代わりに:
使用する
ユースケースに応じては、デフォルト値が適切でない場合があります。
最終更新日 2026年7月2日