はじめに
この記事では、マテリアライズドビュー(Materialized View) について、基本的な概念から実際の使い方まで解説します。
この記事でわかること:
- 通常のビューとマテリアライズドビューの違い
- マテリアライズドビューが必要になる場面
- 作成・リフレッシュ・削除の基本操作(PostgreSQL)
- リフレッシュ戦略の種類と選び方
- 実務で役立つTips
想定読者: SQLの基本(SELECT・JOIN・GROUP BY)を理解しているエンジニア
ビューとは?(前提知識の整理)
マテリアライズドビューを理解するために、まず通常のビュー(View) をおさらいします。
ビューとは、クエリに名前をつけて保存したものです。テーブルのように SELECT で参照できますが、実体はクエリの定義だけであり、データは保持していません。
-- 売上集計ビューの作成
CREATE VIEW daily_sales_summary AS
SELECT
DATE(ordered_at) AS order_date,
SUM(amount) AS total_amount,
COUNT(*) AS order_count
FROM orders
GROUP BY DATE(ordered_at);
-- ビューを参照するたびに、裏でSQLが実行される
SELECT * FROM daily_sales_summary WHERE order_date = '2026-04-20';
ビューの限界
ビューは便利ですが、参照するたびに元のSQLが実行されるという特性があります。
元のクエリが数百万行を集計するような重い処理の場合、毎回そのコストがかかります。アクセスが集中する時間帯には、パフォーマンスの問題につながります。
マテリアライズドビューとは?
マテリアライズドビュー(Materialized View) は、クエリの結果をディスク上に物理的に保存するデータベースオブジェクトです。
「マテリアライズ(Materialize)」は「実体化する」という意味で、クエリ結果をテーブルとして実体化するイメージです。
通常のビューとの違い
| 比較項目 | 通常のビュー | マテリアライズドビュー |
|---|---|---|
| データの保存 | しない(定義のみ) | する(ディスクに保存) |
| 参照時の処理 | 毎回SQLを実行 | 保存済みデータを返す |
| データの鮮度 | 常に最新 | リフレッシュ時点のデータ |
| インデックス | 張れない | 張れる |
| 更新コスト | なし | リフレッシュが必要 |
図にすると以下のようになります。
【通常のビュー】
SELECT → ビュー → 毎回クエリ実行 → テーブル
【マテリアライズドビュー】
SELECT → マテリアライズドビュー(保存済みデータ)← 定期リフレッシュ ← テーブル
どんなときに使うか
- ダッシュボードやレポート用の集計クエリ(毎回重い集計をしたくない場合)
- バッチ処理の結果を高速に参照したい場合
- データウェアハウスでの分析クエリの高速化
なぜマテリアライズドビューが必要なのか
重いクエリの繰り返し実行コスト問題
たとえば、ECサイトの管理画面で「過去1年間の商品カテゴリ別売上集計」を表示するとします。注文テーブルに数千万行あれば、このクエリは毎回数秒〜数十秒かかるかもしれません。
管理者が画面を開くたびにそのクエリが走るのは、DBサーバーへの大きな負担です。
集計・レポーティング用途での有効性
マテリアライズドビューを使えば、集計結果を事前に計算して保存しておき、参照時はその保存済みデータを返すだけにできます。
- 参照が速い(重いSQLを毎回実行しない)
- インデックスを張ってさらに高速化できる
- 元テーブルへの負荷が下がる
リアルタイム性とパフォーマンスのトレードオフ
マテリアライズドビューは「保存した時点のデータ」を返します。元テーブルが更新されても、リフレッシュするまでマテリアライズドビューのデータは古いままです。
- リアルタイム性が必要な場合:通常のビューやテーブル直接参照
- 多少古くてもパフォーマンス優先:マテリアライズドビュー
用途に応じて使い分けることが重要です。
基本的な使い方(PostgreSQL)
ここからはPostgreSQLを例に、基本的な操作を紹介します。
作成
CREATE MATERIALIZED VIEW daily_sales_summary AS
SELECT
DATE(ordered_at) AS order_date,
SUM(amount) AS total_amount,
COUNT(*) AS order_count
FROM orders
GROUP BY DATE(ordered_at);
作成と同時に、クエリが実行されて結果が保存されます。
データを保存せずに定義だけ作りたい場合は WITH NO DATA を使います。
CREATE MATERIALIZED VIEW daily_sales_summary
WITH NO DATA AS
SELECT
DATE(ordered_at) AS order_date,
SUM(amount) AS total_amount,
COUNT(*) AS order_count
FROM orders
GROUP BY DATE(ordered_at);
参照
通常のテーブルやビューと同じように SELECT できます。
SELECT * FROM daily_sales_summary
WHERE order_date = '2026-04-20';
リフレッシュ
元テーブルのデータが更新された後、マテリアライズドビューのデータを最新化するには REFRESH を実行します。
REFRESH MATERIALIZED VIEW daily_sales_summary;
削除
DROP MATERIALIZED VIEW daily_sales_summary;
リフレッシュ戦略
マテリアライズドビューの運用で最も重要なのがリフレッシュ戦略です。
手動リフレッシュ vs 自動リフレッシュ
手動リフレッシュは、アプリケーションやバッチスクリプトから明示的に REFRESH を実行する方法です。PostgreSQLはネイティブの自動リフレッシュ機能を持たないため、pg_cron などの拡張機能やアプリ側のスケジューラーを組み合わせます。
-- pg_cronを使って毎時0分にリフレッシュする例
SELECT cron.schedule('0 * * * *', 'REFRESH MATERIALIZED VIEW daily_sales_summary');
自動リフレッシュをネイティブにサポートするDBもあります(BigQuery、Snowflakeなど)。
完全リフレッシュ vs 増分リフレッシュ
| 方式 | 説明 | メリット | デメリット |
|---|---|---|---|
| 完全リフレッシュ | 全データを削除して再作成 | シンプル | 大テーブルでは時間がかかる |
| 増分リフレッシュ | 変更分だけを反映 | 高速・負荷が小さい | DB・クエリの制約が多い |
PostgreSQLの REFRESH MATERIALIZED VIEW は完全リフレッシュのみ対応しています。増分リフレッシュが必要な場合は、BigQueryやSnowflakeなどのデータウェアハウスが有力な選択肢です。
各DBでの対応状況
| DB | 自動リフレッシュ | 増分リフレッシュ |
|---|---|---|
| PostgreSQL | ✗(外部ツール必要) | ✗ |
| BigQuery | ✓ | ✓(一部クエリのみ) |
| Snowflake | ✓(Dynamic Tables) | ✓ |
| Oracle | ✓ | ✓ |
| MySQL | ✗(ビュー自体が異なる仕様) | ✗ |
Tips
インデックスを張れる
マテリアライズドビューは実データを持つため、インデックスを作成できます。通常のビューにはできない操作です。
-- order_date列にインデックスを作成
CREATE INDEX idx_mv_order_date ON daily_sales_summary (order_date);
これにより、特定の日付での絞り込みがさらに高速になります。
CONCURRENTLY オプション(ロックなしリフレッシュ)
通常の REFRESH は実行中にビューへの読み取りをブロックします。CONCURRENTLY オプションを使うと、リフレッシュ中も参照を受け付け続けられます。
REFRESH MATERIALIZED VIEW CONCURRENTLY daily_sales_summary;
ただし、CONCURRENTLY を使うにはマテリアライズドビューにユニークインデックスが必要です。
-- CONCURRENTLYのためにユニークインデックスが必要
CREATE UNIQUE INDEX idx_mv_order_date_unique ON daily_sales_summary (order_date);
ユースケース別の選択基準
| ユースケース | 推奨アプローチ |
|---|---|
| 毎秒更新が必要なリアルタイム集計 | 通常のビューまたはアプリ側でキャッシュ |
| 1時間〜1日ごとの集計レポート | マテリアライズドビュー + 定期リフレッシュ |
| 大量データの分析クエリ高速化 | マテリアライズドビュー + インデックス |
| ETL後のデータ加工結果を保持 | マテリアライズドビューまたは中間テーブル |
まとめ
この記事では、マテリアライズドビューについて以下の内容を解説しました。
- マテリアライズドビューとは:クエリ結果をディスクに保存するオブジェクト。通常のビューと異なり、参照時に毎回クエリを実行しない
- メリット:重い集計クエリを高速化できる、インデックスを張れる
- デメリット:リフレッシュしないとデータが古くなる、リフレッシュ自体にコストがかかる
-
基本操作:
CREATE/SELECT/REFRESH/DROP - リフレッシュ戦略:用途に応じて手動・自動、完全・増分を使い分ける
-
Tips:
CONCURRENTLYでノンブロッキングリフレッシュが可能
マテリアライズドビューは「パフォーマンスとリアルタイム性のトレードオフ」を理解した上で使うことが大切です。集計処理の速度に課題を感じたら、ぜひ導入を検討してみてください。