メインコンテンツへスキップ
このページでは、プロジェクションの概要、使用方法、およびプロジェクションを操作するための各種オプションについて説明します。

プロジェクションの概要

プロジェクションは、クエリ実行を最適化するフォーマットでデータを格納します。この機能は、次のような場合に役立ちます。
  • 主キーに含まれないカラムに対してクエリを実行する
  • カラムを事前集計し、計算量と IO の両方を削減する
テーブルには 1 つ以上のプロジェクションを定義でき、クエリ解析時には、スキャン対象のデータ量が最も少ないプロジェクションが、ユーザーが指定したクエリを変更することなく ClickHouse によって選択されます。
ディスク使用量プロジェクションは内部的に新しい非表示テーブルを作成するため、より多くの IO とディスク容量が必要になります。 たとえば、プロジェクションで異なる主キーを定義した場合、元のテーブルのすべてのデータが複製されます。
プロジェクションが内部でどのように動作するかについて、より技術的な詳細はこのページで確認できます。

プロジェクションを使う

主キーを使わないフィルタリングの例

テーブルを作成します。
ALTER TABLE を使用すると、既存のテーブルにプロジェクションを追加できます。
データの挿入:
プロジェクションを使うと、元のテーブルで user_namePRIMARY_KEY として定義されていなくても、user_name で高速に絞り込めます。 クエリ時には、データが user_name 順に並んでいるため、プロジェクションを使ったほうが処理されるデータ量が少なくなると ClickHouse が判断します。
クエリでプロジェクションが使用されているかを確認するには、system.query_log テーブルを確認します。projections フィールドには、使用されたプロジェクション名が入り、何も使用されていない場合は空です。

事前集計クエリの例

プロジェクション projection_visits_by_user を持つテーブルを作成します:
データを挿入します:
フィールド user_agent を使って、GROUP BY を含む最初のクエリを実行します。 このクエリでは、事前集計が一致しないため、定義したプロジェクションは使用されません。
projection を利用するには、事前集計と GROUP BY のフィールドの一部またはすべてを選択するクエリを実行できます。
前述のとおり、プロジェクションが使用されたかどうかは system.query_log テーブルを確認することで把握できます。 projections フィールドには、使用されたプロジェクションの名前が表示されます。 プロジェクションが使用されていない場合、このフィールドは空になります。

プロジェクション索引の作成と使用

プロジェクション索引を作成するには、次のようにします。
いくつかのサンプルデータを挿入します:
_part_offset フィールドは、マージやミューテーションを経てもその値が保持されるため、セカンダリ索引で有用です。これはクエリで活用できます:

プロジェクションの操作

プロジェクションに対しては、次の操作を実行できます:

ADD PROJECTION

以下のステートメントを使用して、テーブルのメタデータにプロジェクションの説明を追加します。

WITH SETTINGS

WITH SETTINGS ではプロジェクションレベルの設定を定義し、プロジェクションでのデータの格納方法 (たとえば index_granularityindex_granularity_bytes) をカスタマイズできます。 これらは MergeTree のテーブル設定 に直接対応していますが、適用されるのはこのプロジェクションのみです。 例:
プロジェクション設定は、検証ルールに従い、当該プロジェクションに適用される実効的なテーブル設定を上書きします (例: 無効または互換性のない上書きは拒否されます) 。

DROP PROJECTION

以下のステートメントを使用して、テーブルのメタデータからPROJECTIONの定義を削除し、ディスク上のPROJECTIONファイルを削除します。 これは ミューテーション として実装されています。

MATERIALIZE PROJECTION

以下のステートメントを使用して、パーティション partition_name のPROJECTION name を再構築します。 これは ミューテーション として実装されています。

CLEAR PROJECTION

説明を削除せずにディスク上のPROJECTIONファイルを削除するには、以下のステートメントを使用します。 これは ミューテーション として実装されています。
ADDDROPCLEAR コマンドは、メタデータの変更またはファイルの削除だけを行うという意味で軽量です。 また、これらのコマンドはレプリケーションされ、ClickHouse Keeper または ZooKeeper を介してPROJECTIONのメタデータを同期します。
PROJECTIONの操作は、*MergeTree エンジンのテーブルでのみサポートされます (レプリケーション対応のバリアントを含む) 。

プロジェクションのマージ動作を制御する

クエリを実行すると、ClickHouse は元のテーブルまたはそのプロジェクションのいずれから読み取るかを選択します。 元のテーブルとそのプロジェクションのどちらから読み取るかの判断は、各テーブルパーツごとに個別に行われます。 ClickHouse は一般に、できるだけ少ないデータを読み取ることを目指しており、たとえばパーツの主キーをサンプリングするなど、最適な読み取り元のパーツを特定するためにいくつかの手法を用います。 場合によっては、元のテーブルのパーツに対応するプロジェクションパーツが存在しないことがあります。 これは、たとえば SQL でテーブルにプロジェクションを作成する処理がデフォルトで「遅延的」だからです。つまり、新たに挿入されるデータにのみ影響し、既存のパーツは変更されません。 いずれかのプロジェクションには事前計算済みの集約値がすでに含まれているため、ClickHouse はクエリ実行時に再度集約を行うことを避けるために、対応するプロジェクションパーツから読み取ろうとします。特定のパーツに対応するプロジェクションパーツがない場合、クエリ実行は元のパーツにフォールバックします。 しかし、元のテーブル内の行が、単純ではない data part のバックグラウンドマージによって大きく変化した場合はどうなるでしょうか。 たとえば、そのテーブルが ReplacingMergeTree テーブルエンジンを使用して保存されているとします。 マージ中に同じ行が複数の入力パーツで検出された場合、もっとも新しい行バージョン (もっとも最近に挿入されたパーツのもの) だけが保持され、それ以前のすべてのバージョンは破棄されます。 同様に、テーブルが AggregatingMergeTree テーブルエンジンを使用して保存されている場合、マージ操作によって、入力パーツ内の同じ行が主キーの値に基づいて 1 行にまとめられ、部分的な集約状態が更新されることがあります。 ClickHouse v24.8 より前では、プロジェクションパーツはメインデータと気づかれないまま同期がずれるか、あるいは更新や削除などの特定の操作をまったく実行できませんでした。これは、テーブルにプロジェクションがある場合、データベースが自動的に例外を送出していたためです。 v24.8 以降では、新しいテーブルレベル設定 deduplicate_merge_projection_mode により、前述の単純ではないバックグラウンドマージ操作が元のテーブルのパーツで発生した場合の動作を制御できます。 Delete mutations も、元のテーブルのパーツ内の行を削除する part merge 操作の別の例です。v24.7 以降では、論理削除によってトリガーされる delete mutations に関する動作を制御する設定もあります: lightweight_mutation_projection_mode 以下は、deduplicate_merge_projection_modelightweight_mutation_projection_mode の両方で設定可能な値です。
  • throw (デフォルト): 例外が送出され、プロジェクションパーツの同期ずれを防ぎます。
  • drop: 影響を受けるプロジェクションテーブルパーツは削除されます。影響を受けたプロジェクションパーツについては、クエリは元のテーブルパーツにフォールバックします。
  • rebuild: 影響を受けたプロジェクションパーツは、元のテーブルパーツ内のデータとの整合性を保つために再構築されます。

制限事項

プロジェクションのORDER BY句では、ALIASカラムは使用できません。例:
ALIAS カラムは物理的に保存されず、クエリ時にその場で計算されるため、ソート式が評価されるプロジェクションパートの書き込み処理では使用できません。 代わりに、MATERIALIZED カラムを使用するか、式を直接埋め込んでください。

関連項目

最終更新日 2026年7月2日