メインコンテンツまでスキップ
メインコンテンツまでスキップ

物化ビューとプロジェクション

ユーザーからの一般的な質問は、マテリアライズドビューを使用すべきか、それともプロジェクションを使用すべきかということです。この記事では、両者の主な違いと、特定のシナリオでどちらかを選択する理由について探ります。

主な違いの概要

以下の表は、考慮すべきさまざまな側面におけるマテリアライズドビューとプロジェクションの主な違いをまとめたものです。

課題マテリアライズドビュープロジェクション
データの保存と場所別の明示的なターゲットテーブルに結果を保存し、ソーステーブルへの挿入時に挿入トリガーとして機能します。プロジェクションは、物理的にメインテーブルデータと一緒に保存された最適化されたデータレイアウトを作成し、ユーザーには見えません。
更新メカニズムソーステーブルへのINSERTに対して同期的に操作します(インクリメンタルマテリアライズドビューの場合)。注:リフレッシュ可能なマテリアライズドビューを使用してスケジュールすることもできます。メインテーブルへのINSERTに応じて、非同期的にバックグラウンドで更新されます。
クエリの相互作用マテリアライズドビューを使用する場合、ターゲットテーブルを直接クエリする必要があります。これは、ユーザーがクエリを記述する際にマテリアライズドビューの存在を認識する必要があることを意味します。プロジェクションは、ClickHouseのクエリオプティマイザーによって自動的に選択され、ユーザーがプロジェクションを利用するためにテーブルを修正する必要がないという点で透明です。バージョン25.6からは、複数のプロジェクションでのフィルタリングも可能です。
UPDATE / DELETEの処理マテリアライズドビューは、ソーステーブルに対するUPDATEDELETE操作に自動的に反応しません。これは、マテリアライズドビューがソーステーブルの知識を持たず、ソーステーブルへの挿入トリガーとしてのみ機能するためです。これにより、ソースとターゲットテーブル間のデータの古さが発生する可能性があり、ワークアラウンドや定期的な完全リフレッシュが必要になります。(リフレッシュ可能マテリアライズドビュー経由)。デフォルトでは、DELETED行と互換性がありません(特に軽量削除)。lightweight_mutation_projection_mode(v24.7+)を使用すると互換性が有効になります。
JOINサポートあり。リフレッシュ可能なマテリアライズドビューは、複雑な非正規化に使用できます。インクリメンタルマテリアライズドビューは、左端のテーブル挿入時にのみトリガーされます。なし。プロジェクション定義内でマテリアライズデータをフィルタリングするためのJOIN操作はサポートされていません。
定義内のWHEREはい。マテリアライゼーション前にデータをフィルタリングするために、WHERE句を含めることができます。いいえ。プロジェクション定義内では、マテリアル化されたデータをフィルタリングするためにWHERE句はサポートされていません。
チェイニング機能はい。一つのマテリアライズドビューのターゲットテーブルを他のマテリアライズドビューのソースにすることができ、多段階のパイプラインを可能にします。いいえ。プロジェクションはチェーンできません。
適用可能なテーブルエンジン様々なソーステーブルエンジンで使用できますが、ターゲットテーブルは通常MergeTreeファミリーです。MergeTreeファミリーのテーブルエンジンにのみ利用可能です。
障害処理データ挿入中に障害が発生すると、ターゲットテーブルのデータが失われ、潜在的な不整合が生じます。障害はバックグラウンドで静かに処理されます。クエリはマテリアライズされた部分と非マテリアライズ部分をシームレスに混ぜることができます。
運用オーバーヘッド明示的なターゲットテーブルの作成と、しばしば手動でのバックフィリングが必要です。UPDATE/DELETEに伴う一貫性の管理は、複雑さを増します。プロジェクションは自動的に維持され、同期され、一般的に運用上の負担が軽くなります。
FINALクエリの互換性一般的に互換性がありますが、ターゲットテーブルでGROUP BYが必要な場合が多いです。FINALクエリでは機能しません
レイジーマテリアライゼーションはい。マテリアライゼーション機能を使用する際には、プロジェクションの互換性の問題を監視する必要があります。query_plan_optimize_lazy_materialization = falseを設定する必要があるかもしれません。
並列レプリカはい。いいえ。
optimize_read_in_orderはい。はい。
軽量更新および削除はい。いいえ。

マテリアライズドビューとプロジェクションの比較

マテリアライズドビューを選択する場合

マテリアライズドビューを使用することを検討すべき場合は以下の通りです。

  • リアルタイムETLおよび多段階データパイプラインを使用している:複雑な変換や集計を実行する必要がある、あるいはデータが到着するにつれて複数の段階を経由してルーティングする必要があります。ビューをチェインすることができます。
  • 複雑な非正規化が必要です:複数のソース(テーブル、サブクエリまたは辞書)からデータを事前に結合して、単一のクエリ最適化テーブルにする必要がある、特にリフレッシュ可能なマテリアライズドビューを使用して定期的な完全リフレッシュが許容される場合。
  • 明示的なスキーマ制御が必要:独自のスキーマとエンジンを持つ明示的なターゲットテーブルが必要で、事前に計算された結果のためのデータモデリングに柔軟性を提供します。
  • インジェスト時にフィルタリングしたい:データがマテリアライズされる前にフィルタリングする必要があり、ターゲットテーブルに書き込まれるデータ量を減らします。

マテリアライズドビューを避けるべき場合

マテリアライズドビューの使用を避けるべき場合は以下を考慮するべきです。

  • ソースデータが頻繁に更新または削除される:ソースとターゲットテーブル間の一貫性を処理するための追加の戦略がない場合、インクリメンタルマテリアライズドビューは古くなり、一貫性がなくなる可能性があります。
  • シンプルさと自動最適化が好まれる:別のターゲットテーブルの管理を避けたい場合。

プロジェクションを選択する場合

プロジェクションを使用することを考慮すべき場合は以下の通りです。

  • 単一のテーブルのクエリを最適化する:主な目標は、代替のソート順を提供し、主キーに含まれないカラムのフィルタを最適化し、単一テーブルに対して集計を事前計算することで、単一の基本テーブルに対するクエリを高速化することです。
  • クエリの透明性が重要:クエリが修正なしで元のテーブルを対象にしたい場合、ClickHouseに最適なデータレイアウトを選択させたいです。

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

プロジェクションの使用を避けるべき場合は以下があります。

  • 複雑なデータ変換または多段階ETLが必要:プロジェクションは、その定義内でのJOIN操作をサポートしていないため、多段階パイプラインの構築や、ウィンドウ関数や複雑なCASEステートメントのハンドリングができません。このため、複雑なデータ変換には適していません。
  • マテリアライズされたデータの明示的なフィルタリングが必要:プロジェクションは、その定義内においてデータをマテリアライズするときのフィルタリングのためにWHERE句をサポートしていません。
  • 非MergeTreeテーブルエンジンが使用されている:プロジェクションはMergeTreeファミリーのエンジンを使用するテーブルのみに独占的に利用可能です。
  • FINALクエリが重要:プロジェクションは、重複排除に使用されることがあるFINALクエリでは機能しません。
  • プロジェクションではサポートされないため、並列レプリカが必要です。

概要

マテリアライズドビューとプロジェクションは、クエリの最適化とデータ変換のための強力なツールであり、一般的にはそれらを相互排他的な選択肢と考えるべきではありません。代わりに、クエリから最大限の効果を得るために、補完的に使用することができます。そのため、ClickHouseにおけるマテリアライズドビューとプロジェクションの選択は、実際には特定のユースケースやアクセスパターンに依存します。

一般的な指針として、1つまたは複数のソーステーブルからターゲットテーブルにデータを集計したり、大規模な複雑な変換を実行したりする必要がある場合は、マテリアライズドビューを使用することを検討すべきです。マテリアライズドビューは、クエリ時間から挿入時間への高価な集計の作業を移行するために優れています。それらは、日次または月次のロールアップ、リアルタイムのダッシュボード、またはデータ要約などに優れた選択肢です。

一方で、テーブルの主キーに使用されるカラムとは異なるカラムでフィルタリングするクエリを最適化する必要がある場合はプロジェクションを使用するべきです。主キーが変更不可能になった場合や、アクセスパターンが主キーが対応できるよりも多様である場合には特に便利です。