マテリアライズドビュー(マテビュー)とは?通常ビューとの違いとOracle・PostgreSQLでの作成・リフレッシュ
マテリアライズドビューは、クエリの実行結果をテーブルのように実体として保存しておくデータベースの仕組みです。略して「マテビュー」とも呼ばれます。毎回計算し直す通常のビューと違い、集計済みの結果を保存して再利用するため、重い集計クエリの応答を大きく速くできます。この記事では、通常ビューとの違い、OracleとPostgreSQLそれぞれの作成と自動リフレッシュ、インデックスでの高速化、そして使うべき場面と避けるべき場面までを、実際のSQL構文付きで整理します。
まとめ:マテリアライズドビューの要点
マテリアライズドビューはクエリ結果を物理的に保存し、参照時はその保存済みデータを返します。通常のビューが参照のたびに元テーブルを再計算するのに対し、マテビューは計算を1回で済ませる点が本質的な違いです。代わりに、元データが変わっても自動では追従しないため、リフレッシュ(再計算)で最新化します。OracleとPostgreSQLでは作成・更新の構文が異なります。OracleはREFRESH FAST ON COMMITで差分だけを自動反映でき、これにはマテリアライズド・ビュー・ログが必要です。PostgreSQLは標準のスケジューラを持たないため、REFRESH MATERIALIZED VIEW CONCURRENTLYをpg_cronなどで定期実行します。参照を速くするにはマテビュー自体にインデックスを張ります。更新が激しくリアルタイム性が要るデータには不向きで、集計・分析のように更新が穏やかな用途で効果が出ます。
マテリアライズドビューと通常ビュー・テーブルの違い
マテリアライズドビューを理解する鍵は、通常のビューとテーブルの中間にある存在だと捉えることです。通常ビューは「保存されたクエリ定義」にすぎず、データは持ちません。テーブルはデータを持ちますが、別テーブルの集計を自動で表現はしません。マテビューはその両方の性質を併せ持ち、クエリ結果という形のデータを保存します。三者の違いを整理します。
| 項目 | 通常のビュー | マテリアライズドビュー | テーブル |
|---|---|---|---|
| データ実体 | 持たない | 持つ(結果を保存) | 持つ |
| 参照速度 | 都度計算で遅い | 保存済みで速い | 速い |
| 最新性 | 常に最新 | リフレッシュ時点 | 常に最新 |
| 更新の手間 | 不要 | リフレッシュが必要 | — |
| ストレージ | ほぼ不要 | 結果分が必要 | 必要 |
言い換えると、マテビューは「速さと引き換えに鮮度を一手間で管理する」選択肢です。集計が重く、かつ数分〜数時間の鮮度のずれが許容できるなら効果が大きく、秒単位の最新性が必要なら向きません。集計・分析の用途整理はOLTPとOLAP・DWHの違いと合わせて読むと位置づけが明確になります。
マテリアライズドビューの作成方法(PostgreSQL/Oracle)
作成の基本コマンドはどちらもCREATE MATERIALIZED VIEWですが、リフレッシュ指定の書き方がデータベースで分かれます。代表的なPostgreSQLとOracleを順に示します。
PostgreSQLでの作成(CREATE MATERIALIZED VIEW)
PostgreSQLはシンプルです。SELECTの結果をそのまま保存します。
CREATE MATERIALIZED VIEW sales_summary AS
SELECT region, SUM(amount) AS total
FROM sales
GROUP BY region;
作成直後にデータが格納されます。データを入れず定義だけ作るならWITH NO DATAを付け、後から初回リフレッシュします。PostgreSQLのマテビューは作成時点では更新トリガを持たないため、最新化はリフレッシュ操作で明示的に行います。
Oracleでの作成(BUILDとREFRESH句)
Oracleは作成時にビルドのタイミングとリフレッシュ方式をまとめて指定します。差分更新(FAST)を使うには、元表にマテリアライズド・ビュー・ログを先に作る必要があります。
CREATE MATERIALIZED VIEW LOG ON sales
WITH PRIMARY KEY, ROWID;
CREATE MATERIALIZED VIEW sales_mv
BUILD IMMEDIATE
REFRESH FAST ON COMMIT
AS SELECT region, SUM(amount) AS total
FROM sales GROUP BY region;
BUILD IMMEDIATEは作成と同時にデータを格納し、REFRESH FASTは変更分だけを反映します。ON COMMITを付けると、元表の変更がコミットされた時点で自動的に追従します。ログが無いままFASTを指定すると作成に失敗するため、ログの作成が前提です。
リフレッシュ(更新)と自動化
マテビュー運用の中心はリフレッシュです。手動と自動があり、どちらを選ぶかは鮮度要件とデータベースの機能で決まります。GSCでも「自動リフレッシュ」の検索が多く、ここが実務の関心どころです。
PostgreSQLの更新とpg_cronによる自動化
PostgreSQLはREFRESH MATERIALIZED VIEWで再計算します。通常のリフレッシュは処理中に参照がロックされますが、CONCURRENTLYを付けるとロックせずに差分を反映できます。ただしCONCURRENTLYには、全行を一意に識別できるUNIQUEインデックスが必須です(WHERE付きや式インデックスは不可)。
CREATE UNIQUE INDEX ON sales_summary (region);
SELECT cron.schedule('refresh-sales', '*/10 * * * *',
'REFRESH MATERIALIZED VIEW CONCURRENTLY sales_summary');
PostgreSQLにはジョブスケジューラが標準搭載されていないため、定期実行はpg_cron拡張やOSのcronで組みます。上の例は10分ごとにロックなしで更新します。CONCURRENTLYは新旧の差分を計算する分、通常リフレッシュより時間はかかります。
Oracleの自動リフレッシュ(ON COMMITとON DEMAND)
Oracleは作成時のREFRESH句で自動化を制御します。ON COMMITは元表のコミットごとに自動反映し、手動更新は基本不要です。一方ON DEMANDは明示的な指示でのみ更新し、夜間バッチなど任意のタイミングで回します。手動更新はDBMS_MVIEW.REFRESHで行います。
EXEC DBMS_MVIEW.REFRESH('SALES_MV', 'C');
第2引数の'C'はコンプリート(全件)、'F'はファスト(差分)を表します。更新が常時発生する表にON COMMITを付けるとコミットのたびに負荷がかかるため、更新頻度が高い場合は夜間のON DEMANDへ寄せる判断が要ります。
インデックスによる参照の高速化
マテビューは実体を持つため、テーブルと同じようにインデックスを張れます。保存結果に対して頻繁に絞り込みや結合を行うなら、検索キーにインデックスを作ると応答が縮みます。PostgreSQLでは前述のとおりCONCURRENTLY更新の前提としてUNIQUEインデックスが要るため、設計の初期から検索キーと一意キーを合わせて考えると無駄がありません。インデックスは更新時のコストと引き換えになるので、参照頻度の高い列に絞って張るのが基本です。インデックス種別の選び方はPostgreSQLのGINインデックスも参考になります。
マテリアライズドビューを使うべき場面と避けるべき場面
マテビューは万能ではありません。効くのは、集計や結合が重く、かつ結果の鮮度が分単位〜時間単位で足りる用途です。日次・月次レポート、BIダッシュボードの集計、データウェアハウスの中間集計はその典型で、毎回同じ重いクエリを走らせる無駄をなくせます。
避けたほうがよいのは、元データが秒単位で変わり、常に最新を返す必要がある画面です。注文確定の在庫数や残高表示のように、リフレッシュの遅れがそのまま誤表示になる場面では通常のビューや直接クエリが適します。また、更新が極端に頻繁な表にOracleのON COMMITを付けると、コミットのたびにリフレッシュが走り全体の書き込み性能を下げます。更新が激しいなら自動の差分反映ではなく、夜間バッチでの全件更新に寄せるか、マテビュー自体を見送る判断が現実的です。キャッシュ層の効きはバッファ管理にも左右されるため、データベースのバッファヒット率と併せて見ると効果を見積もりやすくなります。
よくある質問
マテリアライズドビューと通常のビューの違いは何ですか?
通常のビューは保存されたクエリ定義で、参照のたびに元テーブルを計算して最新の結果を返します。マテリアライズドビューはクエリ結果をデータとして保存し、参照時はその保存済みデータを返すため高速です。代わりに元データへ自動では追従せず、リフレッシュで最新化します。常に最新が必要なら通常ビュー、重い集計を高速化したいならマテビュー、という使い分けになります。
マテビューとは何ですか?
マテビューはマテリアライズドビュー(Materialized View)の略称です。意味は同じで、クエリ結果を実体として保存し再利用するデータベースの仕組みを指します。現場では「マテビュー」「MView」「mview」と短く呼ばれることが多く、OracleではMVIEW系の名称やパッケージ名にもこの略が使われます。読み方や表記が揺れても指すものは同じです。
Oracleでマテリアライズドビューを自動リフレッシュするには?
作成時のREFRESH句で指定します。元表のコミットごとに自動反映するならREFRESH FAST ON COMMITを使い、差分更新のために元表へマテリアライズド・ビュー・ログを先に作成します。任意のタイミングで更新するならON DEMANDにしてDBMS_MVIEW.REFRESHをジョブで呼び出します。更新が頻繁な表ではON COMMITの負荷に注意し、夜間バッチへ寄せる選択が安全です。
PostgreSQLでマテリアライズドビューを更新するには?
REFRESH MATERIALIZED VIEW ビュー名で再計算します。参照を止めたくない場合はCONCURRENTLYを付けますが、全行を覆うUNIQUEインデックスが必須です。PostgreSQLはスケジューラを内蔵しないため、定期更新はpg_cron拡張のcron.scheduleやOSのcronでREFRESHを回します。CONCURRENTLYは差分計算を行う分、通常更新より時間がかかります。
マテリアライズドビューにインデックスは作れますか?
作れます。マテビューはデータの実体を持つため、通常のテーブルと同じようにインデックスを張って参照を高速化できます。むしろPostgreSQLでCONCURRENTLY更新を使うにはUNIQUEインデックスが前提になります。既定はB-treeインデックスで等価・範囲検索に効き、検索や結合で頻繁に使う列に絞って張り、更新コストとのバランスを取るのが基本です。インデックスの作りすぎは更新を重くするため、参照頻度の高いキーに限定します。より詳しくは、クライアントサーバモデルの仕組みの記事で整理しています。