0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

マテリアライズドビューとは?仕組みから使い方まで徹底解説

0
Posted at

はじめに

この記事では、マテリアライズドビュー(Materialized View) について、基本的な概念から実際の使い方まで解説します。

この記事でわかること:

  • 通常のビューとマテリアライズドビューの違い
  • マテリアライズドビューが必要になる場面
  • 作成・リフレッシュ・削除の基本操作(PostgreSQL)
  • リフレッシュ戦略の種類と選び方
  • 実務で役立つTips

想定読者: SQLの基本(SELECT・JOIN・GROUP BY)を理解しているエンジニア

ビューとは?(前提知識の整理)

マテリアライズドビューを理解するために、まず通常のビュー(View) をおさらいします。

ビューとは、クエリに名前をつけて保存したものです。テーブルのように SELECT で参照できますが、実体はクエリの定義だけであり、データは保持していません。

create_view.sql
-- 売上集計ビューの作成
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);
use_view.sql
-- ビューを参照するたびに、裏で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.sql
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_no_data.sql
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_mv.sql
SELECT * FROM daily_sales_summary
WHERE order_date = '2026-04-20';

リフレッシュ

元テーブルのデータが更新された後、マテリアライズドビューのデータを最新化するには REFRESH を実行します。

refresh_mv.sql
REFRESH MATERIALIZED VIEW daily_sales_summary;

削除

drop_mv.sql
DROP MATERIALIZED VIEW daily_sales_summary;

リフレッシュ戦略

マテリアライズドビューの運用で最も重要なのがリフレッシュ戦略です。

手動リフレッシュ vs 自動リフレッシュ

手動リフレッシュは、アプリケーションやバッチスクリプトから明示的に REFRESH を実行する方法です。PostgreSQLはネイティブの自動リフレッシュ機能を持たないため、pg_cron などの拡張機能やアプリ側のスケジューラーを組み合わせます。

pg_cron_example.sql
-- 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

インデックスを張れる

マテリアライズドビューは実データを持つため、インデックスを作成できます。通常のビューにはできない操作です。

index_on_mv.sql
-- order_date列にインデックスを作成
CREATE INDEX idx_mv_order_date ON daily_sales_summary (order_date);

これにより、特定の日付での絞り込みがさらに高速になります。

CONCURRENTLY オプション(ロックなしリフレッシュ)

通常の REFRESH は実行中にビューへの読み取りをブロックします。CONCURRENTLY オプションを使うと、リフレッシュ中も参照を受け付け続けられます。

refresh_concurrently.sql
REFRESH MATERIALIZED VIEW CONCURRENTLY daily_sales_summary;

ただし、CONCURRENTLY を使うにはマテリアライズドビューにユニークインデックスが必要です。

unique_index_for_concurrently.sql
-- CONCURRENTLYのためにユニークインデックスが必要
CREATE UNIQUE INDEX idx_mv_order_date_unique ON daily_sales_summary (order_date);

ユースケース別の選択基準

ユースケース 推奨アプローチ
毎秒更新が必要なリアルタイム集計 通常のビューまたはアプリ側でキャッシュ
1時間〜1日ごとの集計レポート マテリアライズドビュー + 定期リフレッシュ
大量データの分析クエリ高速化 マテリアライズドビュー + インデックス
ETL後のデータ加工結果を保持 マテリアライズドビューまたは中間テーブル

まとめ

この記事では、マテリアライズドビューについて以下の内容を解説しました。

  • マテリアライズドビューとは:クエリ結果をディスクに保存するオブジェクト。通常のビューと異なり、参照時に毎回クエリを実行しない
  • メリット:重い集計クエリを高速化できる、インデックスを張れる
  • デメリット:リフレッシュしないとデータが古くなる、リフレッシュ自体にコストがかかる
  • 基本操作CREATE / SELECT / REFRESH / DROP
  • リフレッシュ戦略:用途に応じて手動・自動、完全・増分を使い分ける
  • TipsCONCURRENTLY でノンブロッキングリフレッシュが可能

マテリアライズドビューは「パフォーマンスとリアルタイム性のトレードオフ」を理解した上で使うことが大切です。集計処理の速度に課題を感じたら、ぜひ導入を検討してみてください。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?