マテリアライズドビューとプロジェクションの比較
ユーザーからよく寄せられる質問のひとつが、マテリアライズドビューと プロジェクションのどちらをいつ使うべきかという点です。本記事では、この 2 つの主な違いと、どのような場面で一方を他方より選択すべきかを解説します。
重要な違いのまとめ
以下の表は、検討すべきさまざまな観点における、マテリアライズドビューとプロジェクションの主な違いをまとめたものです。
| Aspect | Materialized views | Projections |
|---|---|---|
| Data storage and location | 結果を別個の明示的なターゲットテーブルに保存し、ソーステーブルへの INSERT 時に挿入トリガーとして動作します。 | プロジェクションは最適化されたデータレイアウトを作成し、物理的にはメインテーブルのデータと並んで保存され、ユーザーからは見えません。 |
| Update mechanism | (インクリメンタルなマテリアライズドビューの場合)ソーステーブルへの INSERT に対して同期的に動作します。注: refreshable materialized view を使用することで、スケジュール実行も可能です。 | メインテーブルへの INSERT 後にバックグラウンドで非同期的に更新されます。 |
| Query interaction | Materialized View を利用するにはターゲットテーブルを直接クエリする必要があり、クエリを書く際にユーザーはマテリアライズドビューの存在を意識する必要があります。 | プロジェクションは ClickHouse のクエリオプティマイザによって自動的に選択されます。ユーザーはプロジェクション付きテーブルに対してクエリを書き換える必要はなく、その点で透過的です。バージョン 25.6 以降では、複数のプロジェクションを条件に応じて併用することも可能です。 |
Handling UPDATE / DELETE | materialized view は、ソーステーブルに関する情報を持たず、ソーステーブルへの挿入トリガーとしてのみ動作するため、ソーステーブルでの UPDATE や DELETE 操作に自動では反応しません。このためソーステーブルとターゲットテーブル間でデータの陳腐化や不整合が生じる可能性があり、回避にはワークアラウンドや、refreshable materialized view による定期的な完全リフレッシュが必要です。 | 既定では、(特に lightweight delete において)DELETED 行とは非互換です。lightweight_mutation_projection_mode(v24.7+)を有効にすることで互換性を持たせることができます。 |
JOIN support | 対応あり。Refreshable materialized view は複雑な非正規化に利用できます。インクリメンタルなマテリアライズドビューは、左端のテーブルへの挿入時のみトリガーされます。 | 対応なし。プロジェクション定義内では、materialized なデータをフィルタリングするための JOIN 操作はサポートされません。ただし、プロジェクションを持つテーブル同士を結合するクエリ自体は通常どおり動作し、プロジェクションは各テーブルへのアクセスを個別に最適化します。 |
WHERE clause in definition | 対応あり。マテリアライズ前にデータをフィルタするために WHERE 句を含めることができます。 | 対応なし。プロジェクション定義内では、materialized なデータをフィルタリングするための WHERE 句はサポートされていません。 |
| Chaining capabilities | 対応あり。あるマテリアライズドビューのターゲットテーブルを別のマテリアライズドビューのソースとして利用でき、多段パイプラインを構成できます。 | 対応なし。プロジェクションを連結(チェーン)することはできません。 |
| Applicable table engines | 各種ソーステーブルエンジンで利用できますが、ターゲットテーブルは通常 MergeTree ファミリーです。 | MergeTree ファミリーのテーブルエンジンに対してのみ利用可能です。 |
| Failure handling | データ挿入中に失敗した場合、ターゲットテーブル側でデータが失われ、整合性に問題が生じる可能性があります。 | 失敗はバックグラウンドでサイレントに処理されます。クエリは materialized なパーツと非 materialized なパーツをシームレスに混在させて参照できます。 |
| Operational overhead | 明示的なターゲットテーブルの作成と、多くの場合手動でのバックフィルが必要です。UPDATE/DELETE と整合性を保つための管理は複雑さを増します。 | プロジェクションは自動的に維持・同期され、一般的に運用上の負荷は低くなります。 |
FINAL query compatibility | 概ね互換性がありますが、ターゲットテーブル上で GROUP BY が必要になることが多いです。 | FINAL クエリとは併用できません。 |
| Lazy materialization | 対応あり。 | materialization 関連機能を使用する際は、プロジェクションの互換性問題に注意してください。必要に応じて query_plan_optimize_lazy_materialization = false を設定する必要があります。 |
| Parallel replicas | 対応あり。 | 対応なし。 |
optimize_read_in_order | 対応あり。 | 対応あり。 |
| Lightweight updates and deletes | 対応あり。 | 対応なし。 |
マテリアライズドビューとプロジェクションの比較
マテリアライズドビューを選択するタイミング
次のような場合は、マテリアライズドビューの利用を検討してください。
- リアルタイム ETL と多段階のデータパイプラインを扱う場合: データが到着したタイミングで複雑な変換や集計を実行したり、ビューを連結することで複数のステージにまたがってデータをルーティングする必要がある場合。
- 複雑な非正規化が必要な場合: 複数のソース(テーブル、サブクエリ、またはディクショナリ)のデータを 1 つのクエリ最適化されたテーブルに事前結合する必要があり、特にリフレッシュ可能なマテリアライズドビューを用いた定期的なフルリフレッシュが許容できる場合。
- スキーマを明示的に制御したい場合: 事前計算済みの結果を保持するために、それ専用のスキーマとエンジンを持つ独立したターゲットテーブルが必要であり、データモデリングの柔軟性を高めたい場合。
- インジェスト時にフィルタリングしたい場合: データがマテリアライズされる_前に_フィルタリングを行い、ターゲットテーブルに書き込まれるデータ量を削減する必要がある場合。
マテリアライズドビューの使用を避けるべき場合
次のような場合には、マテリアライズドビューの使用を避けることを検討してください。
- ソースデータが頻繁に更新または削除される場合: ソーステーブルとターゲットテーブル間の一貫性を保つための追加の戦略がないと、増分マテリアライズドビューは古くなり、一貫性が失われる可能性があります。
- シンプルさや自動最適化を重視する場合: 別個のターゲットテーブルを管理することを避けたい場合。
プロジェクションを選択すべきケース
次のような場合には、プロジェクションの利用を検討してください。
- 単一テーブルに対するクエリの最適化: 主な目的が、単一のベーステーブルに対するクエリを高速化することであり、そのために別のソート順を用意したり、プライマリキーに含まれない列に対するフィルタを最適化したり、単一テーブルに対する集計をあらかじめ計算しておきたい場合。
- クエリの透過性を求める場合: クエリでは元のテーブルをそのまま対象とし、変更を加えずに、特定のクエリに対して ClickHouse が最適なデータレイアウトを自動的に選択するようにしたい場合。
プロジェクションの利用を避けるべき場合
次のような場合には、プロジェクションの使用を避けることを検討してください。
- 複雑なデータ変換や多段階の ETL が必要な場合: プロジェクション定義は
JOIN演算をサポートせず、多段階パイプラインを構築するために連鎖させることもできません。また、ウィンドウ関数や複雑なCASE式など、一部の SQL 機能を扱うこともできません。プロジェクションを持つテーブルに対するクエリは自由に結合できますが、プロジェクション自体は複雑なデータ変換には適していません。 - マテリアライズするデータを明示的にフィルタリングする必要がある場合: プロジェクションは、そのプロジェクションにマテリアライズされるデータをフィルタリングするための
WHERE句を定義内でサポートしていません。 - MergeTree 以外のテーブルエンジンを使用している場合: プロジェクションは、
MergeTreeファミリーのエンジンを使用するテーブルでのみ利用可能です。 FINALクエリが不可欠な場合: プロジェクションは、重複排除などの目的で使用されることがあるFINALクエリとは併用できません。- parallel replicas が必要な場合: parallel replicas はプロジェクションと併用できません。
まとめ
マテリアライズドビューとプロジェクションは、いずれもクエリの最適化やデータ変換のための強力なツールであり、一般的には「どちらか一方だけを選ぶ」ものとして捉える必要はありません。むしろ、両者を補完的に組み合わせて使用することで、クエリから最大限のパフォーマンスを引き出すことができます。そのため、ClickHouse においてマテリアライズドビューとプロジェクションのどちらを選択するかは、特定のユースケースやアクセスパターンに大きく依存します。
一般的な指針として、1 つ以上のソーステーブルからターゲットテーブルへデータを集約したり、大規模かつ複雑な変換処理を行う必要がある場合は、マテリアライズドビューの利用を検討すべきです。マテリアライズドビューは、高コストな集計処理の負荷をクエリ時ではなく挿入時に移すことに非常に優れています。日次・月次ロールアップ、リアルタイムダッシュボード、サマリーデータなどの用途に最適な選択肢です。
一方で、プロジェクションを使うべきなのは、テーブルのプライマリキー(ディスク上のデータの物理的な並び順を決定する列)とは異なる列でフィルタリングするクエリを最適化する必要がある場合です。特に、テーブルのプライマリキーを変更することがもはや不可能な場合や、アクセスパターンがプライマリキーで想定されているものより多様な場合に有用です。