メインコンテンツへスキップ
ユーザーからよく寄せられる質問の 1 つに、materialized view と プロジェクションのどちらを使うべきか、というものがあります。この記事では、この 2 つの主な違いと、 状況に応じてどちらを選ぶべきかを説明します。

主な違いの要約

以下の表は、materialized view とプロジェクションの主な違いを、さまざまな観点から要約したものです。
AspectMaterialized viewsProjections
データの保存場所と配置結果は独立した明示的ターゲットテーブルに保存され、ソーステーブルへの INSERT に対する INSERT 時の insert trigger として動作します。プロジェクションは最適化されたデータレイアウトを作成し、メインテーブルのデータと一緒に物理的に保存され、ユーザーからは見えません。
更新メカニズムソーステーブルへの INSERT に対して同期的に動作します (インクリメンタルmaterialized view の場合) 。注: リフレッシュ可能なマテリアライズドビューを使ってスケジュールすることもできます。メインテーブルへの INSERT に応じて、バックグラウンドで非同期に更新されます。
クエリとの関わりmaterialized view を利用するには、ターゲットテーブルを直接クエリする必要があります。つまり、クエリを書く際には materialized view の存在を意識しておく必要があります。プロジェクションは ClickHouse のクエリオプティマイザによって自動的に選択され、透過的に機能します。そのため、利用するためにユーザーがプロジェクションを持つテーブルへのクエリを変更する必要はありません。バージョン 25.6 以降では、複数のプロジェクションでフィルタすることも可能です。
UPDATE / DELETE の扱いmaterialized view はソーステーブルを認識せず、ソーステーブル への insert trigger としてのみ動作するため、ソーステーブル上の UPDATEDELETE 操作には自動では反応しません。このため、ソーステーブルとターゲットテーブルの間でデータが古くなる可能性があり、回避策または定期的なフルリフレッシュが必要です。 (リフレッシュ可能なマテリアライズドビュー経由)デフォルトでは、DELETED 行と互換性がありません (特に論理削除) 。lightweight_mutation_projection_mode (v24.7+) で互換性を有効にできます。
JOIN のサポートはい。リフレッシュ可能なマテリアライズドビューは複雑な非正規化に使用できます。インクリメンタルmaterialized view は、左端のテーブルへの insert でのみトリガーされます。いいえ。マテリアライズされたデータをフィルタするためのプロジェクション定義内では JOIN 操作はサポートされていません。ただし、プロジェクションを持つテーブルを join するクエリ自体は通常どおり動作します。プロジェクションは個々のテーブルアクセスを最適化します。
定義内の WHERE clauseはい。マテリアライズ前にデータをフィルタするために WHERE 句を含めることができます。いいえ。マテリアライズされたデータをフィルタするためのプロジェクション定義内では WHERE 句はサポートされていません。
連鎖の可否はい。1 つの materialized view のターゲットテーブルを別の materialized view のソースとして使えるため、多段 pipeline を構築できます。いいえ。プロジェクションは連鎖できません。
適用可能なテーブルエンジンさまざまなソーステーブルエンジンで使用できますが、ターゲットテーブルは通常 MergeTree ファミリーです。MergeTree ファミリーのテーブルエンジンでのみ利用可能です。
障害時の扱いデータ挿入中に障害が発生すると、ターゲットテーブル内のデータが失われ、不整合が生じる可能性があります。障害はバックグラウンドで透過的に処理されます。クエリはマテリアライズ済みパーツと未マテリアライズのパーツをシームレスに混在させて扱えます。
運用上のオーバーヘッド明示的なターゲットテーブルの作成が必要で、多くの場合は手動での backfill も必要です。UPDATE/DELETE との整合性管理によって複雑さが増します。プロジェクションは自動的に維持され、同期も保たれるため、一般に運用負荷は低くなります。
FINAL クエリとの互換性一般には互換性がありますが、ターゲットテーブルに対して GROUP BY が必要になることがよくあります。FINAL クエリでは動作しません
遅延マテリアライゼーションはい。マテリアライゼーション機能を使う場合は、プロジェクションとの互換性の問題に注意してください。query_plan_optimize_lazy_materialization = false の設定が必要になる場合があります。
並列レプリカはい。いいえ。
optimize_read_in_orderはい。はい。
論理更新と論理削除はい。いいえ。

materialized view とプロジェクションの比較

materialized viewを選ぶべき場合

次のような場合は、materialized viewの利用を検討してください。
  • リアルタイムETLと多段データパイプラインに対応する場合: 複雑な変換や集計を実行する必要がある、または到着したデータをルーティングする必要があり、viewを連鎖させて複数段階にまたがる処理を行う可能性がある場合。
  • 複雑な非正規化が必要な場合: 複数のソース (テーブル、サブクエリ、または辞書) のデータを、クエリに最適化された単一のテーブルに事前に結合する必要があり、特にリフレッシュ可能なマテリアライズドビューを使用した定期的なフルrefreshを許容できる場合。
  • 明示的なスキーマ制御を行いたい場合: 事前計算された結果を格納するために、独自のスキーマとエンジンを持つ別個のターゲットテーブルが必要であり、データモデリングにより高い柔軟性を求める場合。
  • インジェスト時にfilterしたい場合: データがmaterializedされる_前に_ filterする必要があり、ターゲットテーブルに書き込まれるデータ量を削減したい場合。

materialized viewを避けるべきケース

次のような場合は、materialized viewの使用を避けることを検討してください。
  • ソースデータが頻繁に更新または削除される: ソーステーブルとターゲットテーブルの整合性を保つための追加の対策がないと、インクリメンタルmaterialized viewが古い状態になり、一貫性が失われる可能性があります。
  • シンプルさと自動最適化を重視する: 個別のターゲットテーブルを管理したくない場合です。

プロジェクションを選ぶべき場合

次のような場合は、プロジェクションの使用を検討してください。
  • 単一テーブルのクエリを最適化したい: 主な目的が、別のソート順を用意したり、プライマリキーに含まれないカラムに対するフィルタを最適化したり、単一の基となるテーブルに対する集計を事前計算したりすることで、そのテーブルに対するクエリを高速化することである場合。
  • クエリの透過性を求める: クエリを変更せずに元のテーブルを対象とし、指定したクエリに対して最適なデータレイアウトを ClickHouse に選択させたい場合。

プロジェクションを避けるべき場合

次のような場合は、プロジェクションの使用を避けることを検討してください。
  • 複雑なデータ変換や多段階の ETL が必要な場合: プロジェクション定義では JOIN 操作はサポートされず、多段階パイプラインを構築するために連結することもできません。また、ウィンドウ関数や複雑な CASE ステートメントなど、一部の SQL 機能も扱えません。プロジェクションを持つテーブルに対するクエリでは自由に JOIN できますが、プロジェクション自体は複雑なデータ変換には向いていません。
  • マテリアライズするデータを明示的に絞り込む必要がある場合: プロジェクションでは、プロジェクション自体にマテリアライズされるデータを絞り込むための WHERE 句を定義に含めることはできません。
  • MergeTree 以外のテーブルエンジンを使用している場合: プロジェクションを利用できるのは、MergeTree ファミリーのエンジンを使用するテーブルのみです。
  • FINAL クエリが不可欠な場合: プロジェクションは FINAL クエリでは機能せず、FINAL クエリは重複排除のために使われることがあります。
  • 並列レプリカ が必要な場合: プロジェクションではサポートされていません。

まとめ

materialized view とプロジェクションは、どちらもクエリの最適化やデータ変換に役立つ強力な手段です。一般に、これらは二者択一で考えるべきではありません。むしろ、相互に補完しながら使うことで、クエリの性能を最大限に引き出せます。したがって、ClickHouse で materialized view とプロジェクションのどちらを選ぶかは、最終的には具体的なユースケースとアクセスパターンによって決まります。 一般的な目安として、1 つ以上のソーステーブルからデータを集約してターゲットテーブルに格納したい場合や、大規模な複雑な変換を行いたい場合は、materialized view の利用を検討してください。materialized view は、コストの高い集計処理をクエリ実行時から挿入時へ移すのに非常に適しています。日次または月次のロールアップ、リアルタイムダッシュボード、データのサマリーに適した選択肢です。 一方、テーブルの主キー (ディスク上でのデータの物理的な並び順を決めるキー) に使われているカラムとは異なるカラムでフィルタするクエリを最適化したい場合は、プロジェクションを使うべきです。特に、テーブルの主キーをもはや変更できない場合や、アクセスパターンが主キーだけでは対応しきれないほど多様な場合に有効です。
最終更新日 2026年6月10日