【Oracle】Result Cache完全ガイド|RESULT_CACHEヒント・PL/SQL関数キャッシュ・管理・V$RESULT_CACHE_STATISTICSまで解説

Oracle 11g から導入された Result Cache(結果キャッシュ)は、クエリの実行結果を SGA 内のメモリ領域に保持し、同じ結果を要求する次のクエリではディスクアクセスや計算を省略してキャッシュから直接返す機能です。

参照頻度が高いが更新頻度が低いマスターデータの集計・変換コストの高いビューなどに効果的です。ただし適切な場面で使わないとキャッシュ管理のオーバーヘッドが逆効果になります。

この記事でわかること

  • Result Cache の仕組みと自動無効化(ベーステーブルへの DML で無効化される)
  • RESULT_CACHE ヒントを使って SQL の結果をキャッシュする方法
  • PL/SQL ファンクションに RESULT_CACHE オプションを付けてキャッシュする方法
  • RESULT_CACHE_MODE パラメータで自動キャッシュを有効にする方法
  • V$RESULT_CACHE_STATISTICS・V$RESULT_CACHE_OBJECTS でキャッシュの状態を確認する
  • キャッシュを手動でフラッシュ・無効化する方法
スポンサーリンク

Result Cache の仕組みと自動無効化

Result Cache は SGA の Shared Pool 内(またはセパレートな領域)に確保されます。キャッシュのキーは SQL テキスト + バインド変数の値 + 依存テーブルのバージョンです。

最も重要な特性は自動無効化です。依存するベーステーブルに対して DML(INSERT・UPDATE・DELETE)が実行されてコミットされると、そのテーブルを参照するすべての Result Cache エントリが自動的に無効化されます。

キャッシュに向く場面 キャッシュに向かない場面
マスターデータの集計(更新頻度が低い) リアルタイムデータ(頻繁に更新されるテーブル)
集計コストが高いが結果は安定している SYSDATE・SYS_GUID など非決定的関数を含む SQL
同じ条件で繰り返し実行される参照クエリ 1回しか実行されない SQL
PL/SQL から繰り返し呼ばれる定数ルックアップ関数 行ごとに異なる引数が渡される関数

SQL の結果をキャッシュする(RESULT_CACHE ヒント)

RESULT_CACHE ヒントで SQL 結果をキャッシュする
-- /*+ RESULT_CACHE */ ヒントでクエリ結果をキャッシュ
SELECT /*+ RESULT_CACHE */
    d.department_id,
    d.department_name,
    COUNT(e.employee_id)      AS emp_count,
    ROUND(AVG(e.salary), 0)  AS avg_salary
FROM departments d
LEFT JOIN employees e ON d.department_id = e.department_id
GROUP BY d.department_id, d.department_name
ORDER BY d.department_id;

-- 2回目の実行: Result Cache からデータが返る(物理 I/O なし)
-- ベーステーブル(departments/employees)が更新されると自動で無効化される
NO_RESULT_CACHE ヒントでキャッシュを抑制する
-- 全体設定でキャッシュが有効な環境でも特定 SQL はキャッシュしない
SELECT /*+ NO_RESULT_CACHE */ *
FROM orders
WHERE order_date >= SYSDATE - 1;  -- SYSDATE を含む → キャッシュ不適切

RESULT_CACHE_MODE で自動キャッシュを有効にする

ヒントを書かなくても自動的にキャッシュする設定もありますが、予期しないキャッシュが発生するため通常は MANUAL(デフォルト)が推奨です。

RESULT_CACHE_MODE の確認と変更
-- 現在のモードを確認(デフォルト: MANUAL)
SHOW PARAMETER result_cache_mode;

-- セッションレベルで FORCE に変更(HINT なしでも全クエリをキャッシュしようとする)
ALTER SESSION SET result_cache_mode = FORCE;

-- システムレベルで変更(通常は推奨しない)
ALTER SYSTEM SET result_cache_mode = FORCE SCOPE=BOTH;
-- MANUAL に戻す
ALTER SYSTEM SET result_cache_mode = MANUAL SCOPE=BOTH;

PL/SQL ファンクションの結果をキャッシュする

PL/SQL ファンクションに RESULT_CACHE オプションを付けると、同じ引数で呼んだときにキャッシュされた値を返します。コード変換・計算コストの高い参照関数に効果的です。

RESULT_CACHE オプション付きのファンクション
-- 部門名を返すルックアップ関数(頻繁に呼ばれるが DB 更新頻度が低い)
CREATE OR REPLACE FUNCTION get_department_name(
    p_dept_id IN departments.department_id%TYPE
)
RETURN VARCHAR2
RESULT_CACHE RELIES_ON (departments)   -- 依存テーブルを明示(Oracle 11g)
-- Oracle 12c 以降は RELIES_ON を省略しても自動検出
AS
    v_name departments.department_name%TYPE;
BEGIN
    SELECT department_name
    INTO v_name
    FROM departments
    WHERE department_id = p_dept_id;

    RETURN v_name;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        RETURN NULL;
END get_department_name;
/

-- 使用例: 同じ引数で2回目以降はキャッシュから返る
SELECT employee_id, get_department_name(department_id) AS dept_name
FROM employees
WHERE department_id IN (10, 20, 50);
RESULT_CACHE 使用時の制約

  • OUT パラメータ・IN OUT パラメータを持つファンクションには使用不可
  • SYSDATE・SYSTIMESTAMP・SYS_GUID など非決定的な値を返すファンクションには不適切
  • 依存テーブルへのDMLがコミットされると自動でキャッシュが無効化される
  • ファンクション内で DML を実行している場合は使用不可

Result Cache の状態を監視する

V$RESULT_CACHE_STATISTICS でキャッシュ統計を確認する
-- Result Cache の全体統計を確認
SELECT name, value
FROM V$RESULT_CACHE_STATISTICS
ORDER BY name;
-- 主要な統計:
-- Block Count Maximum: キャッシュの最大ブロック数
-- Block Count Current: 現在使用中のブロック数
-- Result Size Maximum (Blocks): 1エントリの最大サイズ(ブロック)
-- Create Count Success: キャッシュ作成成功件数
-- Find Count: キャッシュヒット件数
-- Invalidation Count: 無効化件数
V$RESULT_CACHE_OBJECTS でキャッシュエントリを確認する
-- キャッシュされている SQL とその統計を確認
SELECT
    id,
    type,          -- RESULT(SQL キャッシュ)または DEPENDENCY(依存テーブル)
    status,        -- PUBLISHED(有効)/ INVALID(無効)
    name,          -- SQL テキストまたはオブジェクト名
    scan_count,    -- スキャン(ヒット)回数
    invalidations, -- 無効化された回数
    ROUND(lru_number)  AS lru_priority
FROM V$RESULT_CACHE_OBJECTS
WHERE type = 'RESULT'
  AND status = 'PUBLISHED'
ORDER BY scan_count DESC
FETCH FIRST 10 ROWS ONLY;

Result Cache の管理(フラッシュ・サイズ変更)

Result Cache を手動フラッシュする
-- 全 Result Cache を無効化する(メンテナンス時など)
BEGIN
    DBMS_RESULT_CACHE.FLUSH;
END;
/

-- キャッシュの状態レポートを表示する
BEGIN
    DBMS_RESULT_CACHE.MEMORY_REPORT;
END;
/
Result Cache のサイズを確認・変更する
-- Result Cache に割り当てられたメモリサイズを確認
SHOW PARAMETER result_cache_max_size;
-- デフォルト: SGA の 0.5%(ASMM モード)または1MB

-- Result Cache のサイズを増やす(例: 64MB)
ALTER SYSTEM SET result_cache_max_size = 64M SCOPE=BOTH;

-- 1エントリの最大サイズを確認
SHOW PARAMETER result_cache_max_result;
-- デフォルト: result_cache_max_size の 5%

まとめ

  • RESULT_CACHE ヒント:対象 SQL に直接付与。ベーステーブルが更新されると自動で無効化される
  • PL/SQL RESULT_CACHE:ファンクション定義に追加。同じ引数の繰り返し呼び出しを高速化する
  • 自動無効化:ベーステーブルへのコミット済み DML で即時無効化。更新頻度が高いテーブルには不向き
  • V$RESULT_CACHE_STATISTICS:ヒット率・無効化回数でキャッシュの効果を定量評価できる
  • MANUAL モード推奨:RESULT_CACHE_MODE=FORCE は予期しないキャッシュが発生するため通常は MANUAL を使いヒントで制御する

バッファキャッシュ・共有プールなど SGA 全体のメモリ管理はSGA・PGAメモリ管理完全ガイドを参照してください。パフォーマンスチューニング全般のアプローチは 遅いSQLを特定する方法完全ガイドも参照してください。