Oracleマテリアライズドビューの作成と管理【高速化・定期更新完全ガイド】

当ページのリンクには広告が含まれています。

「複雑な集計クエリが遅い」「毎回同じ重いJOINを実行している」——そんなときに使えるのがマテリアライズドビュー(MV)です。集計結果を物理的に保存しておき、高速にアクセスできるOracle固有の機能を解説します。

目次

1. マテリアライズドビューとは(通常ビューとの違い) {#about}

比較項目通常ビュー(VIEW)マテリアライズドビュー(MV)
データの保存保存しない(SQLを保存するだけ)物理的に結果を保存
アクセス速度毎回元テーブルを参照(遅い場合あり)保存済み結果を読むだけ(高速)
データの新鮮さ常に最新リフレッシュするまで古い場合がある
用途権限管理・複雑なSQLの簡略化集計高速化・DWH・レポート

マテリアライズドビューが効果的なケース:

  • 毎時・毎日集計する大量データのレポート
  • 複数テーブルのJOIN結果を繰り返し使う
  • リモートDBのデータをローカルにキャッシュする(DBリンク経由)

2. マテリアライズドビューの作成 {#create-mv}

シンプルな集計MVを作成

-- 部門ごとの給与集計をMVとして保存
CREATE MATERIALIZED VIEW MV_DEPT_SALARY
AS
SELECT
    department_id,
    COUNT(*) AS headcount,
    AVG(salary) AS avg_salary,
    MAX(salary) AS max_salary,
    SUM(salary) AS total_salary
FROM employees
GROUP BY department_id;

リフレッシュ設定付きで作成(推奨)

CREATE MATERIALIZED VIEW MV_DEPT_SALARY
REFRESH FAST             -- 差分更新(FAST/COMPLETE/FORCE/NEVER)
ON DEMAND                -- 手動でリフレッシュ(ON COMMIT/ON DEMANDから選択)
WITH QUERY REWRITE       -- クエリリライトを有効化
AS
SELECT
    department_id,
    COUNT(*) AS headcount,
    SUM(salary) AS total_salary
FROM employees
GROUP BY department_id;

自動リフレッシュ(スケジュール付き)

CREATE MATERIALIZED VIEW MV_MONTHLY_SALES
REFRESH COMPLETE
START WITH SYSDATE
NEXT TRUNC(SYSDATE + 1)        -- 翌日0時から毎日更新
AS
SELECT
    TRUNC(sale_date, 'MM') AS sale_month,
    region,
    SUM(amount) AS total_amount
FROM sales
GROUP BY TRUNC(sale_date, 'MM'), region;

3. リフレッシュ(更新)の方法と設定 {#refresh}

リフレッシュの種類

種類内容速度条件
COMPLETEMVを全削除して再作成遅いいつでも使用可能
FAST変更分のみ更新(差分更新)速いマテリアライズドビューログが必要
FORCEFASTが可能ならFAST、不可ならCOMPLETE自動判断
NEVER自動リフレッシュしない手動のみ

FAST リフレッシュに必要なマテリアライズドビューログの作成

-- 元テーブル(employees)にMVログを作成(FASTリフレッシュの前提)
CREATE MATERIALIZED VIEW LOG ON employees
WITH ROWID, SEQUENCE (employee_id, department_id, salary)
INCLUDING NEW VALUES;

手動でリフレッシュする

-- 単一MVをCOMPLETEリフレッシュ
BEGIN
    DBMS_MVIEW.REFRESH('MV_DEPT_SALARY', 'C');  -- C=COMPLETE, F=FAST
END;
/

-- 複数MVを一括リフレッシュ
BEGIN
    DBMS_MVIEW.REFRESH_ALL_MVIEWS(out_failures => 0);
END;
/

-- 依存関係順にリフレッシュ
BEGIN
    DBMS_MVIEW.REFRESH_DEPENDENT(list => 'EMPLOYEES');
END;
/

4. クエリリライト(自動高速化) {#query-rewrite}

クエリリライトとは、元テーブルへのクエリを自動的にMVへのクエリに書き換えてくれる機能です。

-- MVを作成するときにWITH QUERY REWRITEを指定
CREATE MATERIALIZED VIEW MV_DEPT_SALARY
ENABLE QUERY REWRITE
AS
SELECT department_id, SUM(salary) AS total
FROM employees
GROUP BY department_id;
-- 元テーブルへのクエリ(オプティマイザが自動的にMVを使う)
SELECT department_id, SUM(salary)
FROM employees
GROUP BY department_id;
-- → 内部的に MV_DEPT_SALARY から読む(高速)

クエリリライトが機能しているか確認:

EXPLAIN PLAN FOR
SELECT department_id, SUM(salary)
FROM employees
GROUP BY department_id;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
-- 実行計画に MV_DEPT_SALARY が表示されればリライト成功

5. マテリアライズドビューの確認と管理 {#check-mv}

一覧の確認

SELECT
    MVIEW_NAME,
    REFRESH_METHOD,
    REFRESH_MODE,
    LAST_REFRESH_TYPE,
    LAST_REFRESH_DATE,
    COMPILE_STATE
FROM USER_MVIEWS
ORDER BY MVIEW_NAME;

COMPILE_STATEの値:

意味
VALID正常
NEEDS_COMPILE元テーブルの変更でMVが無効化(コンパイルが必要)
ERRORエラーあり

MVを再コンパイル

-- 元テーブルのDDL変更後にMVが無効になった場合
ALTER MATERIALIZED VIEW MV_DEPT_SALARY COMPILE;

MVの削除

DROP MATERIALIZED VIEW MV_DEPT_SALARY;

6. よくあるエラーと対処 {#errors}

ORA-23413:テーブルにマテリアライズドビューログがない

ORA-23413: "SCOTT"."EMPLOYEES"にマテリアライズド・ビュー・ログがありません

FASTリフレッシュを使う場合はMVログが必要です。

CREATE MATERIALIZED VIEW LOG ON employees
WITH ROWID, SEQUENCE (department_id, salary)
INCLUDING NEW VALUES;

ORA-12054:ON COMMITリフレッシュはサポートされない

集計(GROUP BY・DISTINCT)を含むMVにはON COMMITは使えません。ON DEMANDに変更します。

MVのデータが古い

手動リフレッシュが必要な場合、または自動リフレッシュのスケジュールを確認します。

-- 最終リフレッシュ日時を確認
SELECT MVIEW_NAME, LAST_REFRESH_DATE FROM USER_MVIEWS;

-- 手動で更新
EXEC DBMS_MVIEW.REFRESH('MV_DEPT_SALARY', 'C');

7. まとめ:MV活用チェックリスト {#summary}

設計時
□ FAST リフレッシュを使う場合は元テーブルに MV LOG を作成
□ ON COMMIT は単純な集計MVに限定(制約が多い)
□ リフレッシュ頻度はデータの鮮度要件に合わせて設定

運用時
□ USER_MVIEWS で COMPILE_STATE が VALID か定期確認
□ LAST_REFRESH_DATE で更新が滞っていないか確認
□ 元テーブルのDDL変更後は ALTER MATERIALIZED VIEW ... COMPILE で再コンパイル

パフォーマンス
□ ENABLE QUERY REWRITE を指定してクエリリライトを有効化
□ EXPLAIN PLAN でMVが使われているか確認
□ リフレッシュ処理中はMVが書き込みロックされるため、時間帯に注意

関連記事:

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

ITの事や自分の経験談など綴っていきたいと思っています。

コメント

コメントする

CAPTCHA


目次