PL/SQLファンクション結果キャッシュ
PL/SQLファンクションにRESULT_CACHE
オプションを指定すると、その結果がキャッシュされるようになります。これにより、セッションは、キャッシュされた結果を再使用できるようになります(結果が利用可能な場合)。
Oracle Databaseでは、結果がキャッシュされるファンクションの実行中に問合せが行われるすべてのデータ・ソース(表およびビュー)が自動的に検出されます。これらのデータ・ソースのいずれかに対する変更がコミットされると、キャッシュされた結果は、すべてのインスタンスに渡って無効になります。結果キャッシュの対象として最良のファンクションは、頻繁に起動され、ほとんどまたはまったく変更されない情報に依存するファンクションです。
結果オブジェクトは、問合せまたは結果がキャッシュされるファンクションの実行結果です。一時オブジェクトは、RESULT_CACHE_MAX_SIZE
とRESULT_CACHE_MAX_RESULT
パラメータの乗算で設定された制限を超える問合せまたは結果がキャッシュされるファンクションの実行結果です。一時オブジェクトは、SYSユーザーに対して定義された一時表領域に格納される一時セグメントです。
結果オブジェクトと一時オブジェクトを一緒に表示するには、一時オブジェクトにTempタイプを使用し、結果オブジェクトにResultタイプを使用してV$RESULT_CACHE_OBJECTS
を結合します。
SELECT rc1.NAME, rc2.STATUS, rc3.STATUS, rc2.BLOCK_COUNT FROM V$RESULT_CACHE_OBJECTS rc1, V$RESULT_CACHE_OBJECTS rc2 WHERE rc1.TYPE = 'Result' AND rc2.TYPE = 'Temp' AND rc1.CACHE_KEY = rc2.CACHE_KEY;
RESULT_CACHE_MAX_TEMP_SIZE
パラメータは、結果キャッシュがPDBで消費できる一時表領域の最大量を設定します。
結果キャッシュの使用量は、アプリケーション・ワークロードの変更に基づいて最適なパフォーマンスを得るために最適化されます。
キャッシュされた結果をリモート・インスタンスからフェッチする前に、データベースはヒューリスティックを使用して、ローカル・インスタンスで結果を再計算するほうが効率的かどうかを判断します。
Oracle Databaseは、最近使用された結果がキャッシュされるファンクションを追跡します。この履歴を使用することで、データベースは最近の履歴にx回出現する、結果がキャッシュされるファンクションと引数のペアのみをキャッシュします。このxは、初期化パラメータRESULT_CACHE_EXECUTION_THRESHOLD
で設定します。デフォルト値が2の場合、結果は2番目の実行でキャッシュされ、3番目の実行で再利用されます。
次の問合せを実行して、結果キャッシュの状態を評価できます。キャッシュされたファンクションの再利用率の分布が表示されます。これらの結果の大部分のスキャン数が0であることに気付いた場合は、RESULT_CACHE_EXECUTION_THRESHOLD
の値を1または2増やすことを検討してください。
SELECT SCAN_COUNT, COUNT(CACHE_KEY) FROM V$RESULT_CACHE_OBJECTS WHERE NAMESPACE = 'PLSQL' GROUP BY SCAN_COUNT;
ここでのトピック
ファンクションの結果キャッシュの有効化
ファンクションの結果がキャッシュされるようにするには、ファンクションの宣言と定義にRESULT_CACHE
句を含めます。構文の詳細は、「ファンクションの宣言および定義」を参照してください。
ノート:
データベース・サーバーの結果キャッシュの構成と管理の詳細は、『Oracle Databaseリファレンス』および『Oracle Databaseパフォーマンス・チューニング・ガイド』を参照してください。
例9-39では、パッケージdepartment_pkg
が、結果がキャッシュされるファンクションget_dept_info
を宣言し、定義しています(このファンクションによって、指定した部門に関する情報のレコードが戻されます)。このファンクションは、データベース表のDEPARTMENTS
およびEMPLOYEES
に依存します。
ファンクションget_dept_info
は、他のファンクションを起動する場合と同様に起動します。たとえば、次の起動では、部門番号10に関する情報のレコードが戻されます。
department_pkg.get_dept_info(10);
次の起動では、部門番号10の名前のみが戻されます。
department_pkg.get_dept_info(10).dept_name;
get_dept_info(10)
の結果が結果キャッシュに含まれている場合、結果はこのキャッシュから戻されますが、そうでない場合は、結果は計算されてキャッシュに追加されます。get_dept_info
はDEPARTMENTS
表およびEMPLOYEES
表に依存するため、DEPARTMENTS
またはEMPLOYEES
への変更がコミットされると、get_dept_info
のキャッシュされた結果はすべて無効になり、DEPARTMENTS
またはEMPLOYEES
が変更される可能性のあるすべての場所で、キャッシュ無効化ロジックをプログラミングする必要がなくなります。
例9-39 結果がキャッシュされるファンクションの宣言および定義
CREATE OR REPLACE PACKAGE department_pkg AUTHID DEFINER IS TYPE dept_info_record IS RECORD ( dept_name departments.department_name%TYPE, mgr_name employees.last_name%TYPE, dept_size PLS_INTEGER ); -- Function declaration FUNCTION get_dept_info (dept_id NUMBER) RETURN dept_info_record RESULT_CACHE; END department_pkg; / CREATE OR REPLACE PACKAGE BODY department_pkg IS -- Function definition FUNCTION get_dept_info (dept_id NUMBER) RETURN dept_info_record RESULT_CACHE IS rec dept_info_record; BEGIN SELECT department_name INTO rec.dept_name FROM departments WHERE department_id = dept_id; SELECT e.last_name INTO rec.mgr_name FROM departments d, employees e WHERE d.department_id = dept_id AND d.manager_id = e.employee_id; SELECT COUNT(*) INTO rec.dept_size FROM EMPLOYEES WHERE department_id = dept_id; RETURN rec; END get_dept_info; END department_pkg; /
結果がキャッシュされるファンクションを使用するアプリケーションの開発
結果がキャッシュされるファンクションを使用するアプリケーションを開発する場合、指定したパラメータ値のセットに対してそのファンクションの本体が実行される回数については何も想定しないでください。
結果がキャッシュされるファンクションの本体が実行される状況をいくつか次に示します。
-
このデータベース・インスタンスでのセッションが、これらのパラメータ値を使用してファンクションを初めて起動し、実行されたとき
ノート:
RESULT_CACHE_EXECUTION_THRESHOLD
は、ファンクションと特定の引数セットがキャッシュされるまでに表示する必要がある回数を指定します。そのパラメータのデフォルト値は2で、システム・レベルで構成できます。 -
これらのパラメータ値のキャッシュされた結果が無効である場合
ファンクションが依存するいずれかのデータソースに対する変更がコミットされると、キャッシュされている結果が無効になります
-
これらのパラメータ値のキャッシュされた結果がエージ・アウトされた場合
システムでメモリーが必要な場合は、PL/SQLファンクション履歴追跡に基づいて、最も古いキャッシュ値またはほとんど使用されないキャッシュ値が破棄される可能性があります。
DBMS_RESULT_CACHE
ブロック・リスト・プロシージャを起動して、一部の結果キャッシュ関連オブジェクトがローカル・インスタンスまたはグローバルにキャッシュされないように明示的にブロックする場合DBMS_RESULT_CACHE.FLUSH
が実行され、SQL問合せのキャッシュされたすべての結果およびPL/SQLファンクションのキャッシュされたすべての結果がフラッシュされた後-
ファンクションがキャッシュをバイパスする場合(「結果キャッシュのバイパス」を参照)
結果がキャッシュされるファンクションの要件
結果がキャッシュされるPL/SQLファンクションは、あらゆる入力に対して生成される出力が、RESULT_CACHE
のマークが付けられていなかった場合に生成される出力と常に同じになるときに安全です。この安全性は、次に示す条件が満たされている場合にのみ保証されます。
-
ファンクションの実行時に、副作用がないこと。
副作用の詳細は、「サブプログラムの副作用」を参照してください。
-
ファンクションがアクセスするすべての表が、そのファンクションと同じデータベース内に存在する、通常の非
SYS
所有の永続的な表であること。 -
ファンクションの結果は、常に、そのファンクションが参照する表の現在の
SCN
でコミットされた内容とあわせた、入力実績のベクトルによってのみ決定されること。
結果がキャッシュされるファンクションでは、次の条件も満たされていることがお薦めされています。
-
セッション固有の設定に依存しない。
詳細は、「結果がキャッシュされるファンクションによるセッション固有の設定の処理」を参照してください。
-
セッション固有のアプリケーション・コンテキストに依存しない。
詳細は、「結果がキャッシュされるファンクションによるセッション固有のアプリケーション・コンテキストの処理」を参照してください。
詳細は、『Oracle Databaseパフォーマンス・チューニング・ガイド』を参照してください。
結果がキャッシュされるファンクションの例
結果キャッシュの対象として最良のファンクションは、(最初の例がこれに該当している可能性がありますが)頻繁に起動され、ほとんど変更されない情報に依存するファンクションです。結果キャッシュを行うことによって、再帰ファンクションでの冗長計算が回避されます。
例:
結果がキャッシュされるアプリケーション構成パラメータ
グローバル・レベル、アプリケーション・レベルまたはロール・レベルのいずれのレベルで設定できる構成パラメータを持つアプリケーションについて考えてみます。このアプリケーションは、構成情報を次の表に格納します。
-- Global Configuration Settings
DROP TABLE global_config_params;
CREATE TABLE global_config_params
(name VARCHAR2(20), -- parameter NAME
val VARCHAR2(20), -- parameter VALUE
PRIMARY KEY (name)
);
-- Application-Level Configuration Settings
CREATE TABLE app_level_config_params
(app_id VARCHAR2(20), -- application ID
name VARCHAR2(20), -- parameter NAME
val VARCHAR2(20), -- parameter VALUE
PRIMARY KEY (app_id, name)
);
-- Role-Level Configuration Settings
CREATE TABLE role_level_config_params
(role_id VARCHAR2(20), -- application (role) ID
name VARCHAR2(20), -- parameter NAME
val VARCHAR2(20), -- parameter VALUE
PRIMARY KEY (role_id, name)
);
各構成パラメータで、ロール・レベルの設定はアプリケーション・レベルの設定をオーバーライドし、アプリケーション・レベルの設定はグローバル設定をオーバーライドします。パラメータに適用される設定を決定するために、このアプリケーションはPL/SQLファンクションget_value
を定義します。パラメータ名、アプリケーションIDおよびロールIDを指定すると、get_value
はそのパラメータに適用される設定を戻します。
ファンクションget_value
が頻繁に起動され、構成情報はほとんど変更されない場合、このファンクションは結果キャッシュの対象として最良のファンクションとなります。
例9-40に、get_value
に指定可能な定義を示します。あるパラメータ値のセットに対して、グローバル設定によってget_value
の結果が決まるとします。get_value
の実行中に、データベースでは3つの表role_level_config_params
、app_level_config_params
およびglobal_config_params
の問合せが検出されます。これらの3つの表のいずれに対する変更がコミットされても、このパラメータ値のセットについてキャッシュされた結果は無効となり、再計算する必要があります。
次に、2番目のパラメータ値セットに対して、ロール・レベルの設定によってget_value
の結果が決定されるとします。get_value
の実行中に、データベースでは表role_level_config_params
の問合せのみが検出されます。role_level_config_params
に対する変更がコミットされると、2番目のパラメータ値セットについてキャッシュされた結果は無効となりますが、app_level_config_params
またはglobal_config_params
に対する変更がコミットされてもキャッシュされた結果には影響がありません。
例9-40 構成パラメータの設定を返す、結果がキャッシュされるファンクション
CREATE OR REPLACE FUNCTION get_value
(p_param VARCHAR2,
p_app_id NUMBER,
p_role_id NUMBER
)
RETURN VARCHAR2
RESULT_CACHE
AUTHID DEFINER
IS
answer VARCHAR2(20);
BEGIN
-- Is parameter set at role level?
BEGIN
SELECT val INTO answer
FROM role_level_config_params
WHERE role_id = p_role_id
AND name = p_param;
RETURN answer; -- Found
EXCEPTION
WHEN no_data_found THEN
NULL; -- Fall through to following code
END;
-- Is parameter set at application level?
BEGIN
SELECT val INTO answer
FROM app_level_config_params
WHERE app_id = p_app_id
AND name = p_param;
RETURN answer; -- Found
EXCEPTION
WHEN no_data_found THEN
NULL; -- Fall through to following code
END;
-- Is parameter set at global level?
SELECT val INTO answer
FROM global_config_params
WHERE name = p_param;
RETURN answer;
END;
/
結果がキャッシュされる再帰ファンクション
フィボナッチ数列の数学的定義を模倣した、フィボナッチ数列のn番目の項を検索するための再帰ファンクションは、多くの冗長計算を実行する可能性があります。たとえば、fibonacci(7)
を評価するために、このファンクションはfibonacci(6)
およびfibonacci(5)
を計算する必要があります。fibonacci(6)
を計算するために、このファンクションはfibonacci(5)
およびfibonacci(4)
を計算する必要があります。このため、fibonacci(5)
などのいくつかの項は、重複して計算されます。結果キャッシュを行うことによって、これらの冗長計算が回避されます。
ノート:
キャッシュされる再帰的起動の数は、最大で128です。
CREATE OR REPLACE FUNCTION fibonacci (n NUMBER)
RETURN NUMBER
RESULT_CACHE
AUTHID DEFINER
IS
BEGIN
IF (n =0) OR (n =1) THEN
RETURN 1;
ELSE
RETURN fibonacci(n - 1) + fibonacci(n - 2);
END IF;
END;
/
結果がキャッシュされるファンクションの高度なトピック
ここでのトピック
キャッシュ・ヒットの規則
結果がキャッシュされるファンクションが異なるパラメータ値で起動されるたびに、それらのパラメータおよびそれぞれの結果がキャッシュに格納されます。それ以降、同じファンクションが同じパラメータ値で起動されると(つまり、キャッシュ・ヒットがある場合)、結果は再計算されるのではなく、キャッシュから取り出されます。
キャッシュ・ヒット用のパラメータ比較の規則は、次に示すように、PL/SQLの「等号」(=)演算子の規則とは異なります。
カテゴリ | キャッシュ・ヒットの規則 | 「等号」演算子の規則 |
---|---|---|
NULLの比較 |
|
|
NULLでないスカラーの比較 |
NULLでないスカラーは、それぞれの値が同一である場合にのみ同じとなります(つまり、指定されたプラットフォームでそれぞれの値が同一のビット・パターンを持っている場合にのみ同じとなります)。たとえば、 |
NULLでないスカラーは、指定されたプラットフォームでそれぞれの値が同一のビット・パターンを持っていない場合でも、等しくなる可能性があります。たとえば、 |
結果キャッシュのバイパス
場合によって、キャッシュはバイパスされます。キャッシュがバイパスされる場合を次に示します。
-
ファンクションが結果をキャッシュから取り出すのではなく、計算する場合。
-
ファンクションが計算する結果がキャッシュに追加されない場合。
キャッシュがバイパスされる場合の例を次にいくつか示します。
-
すべてのセッションでキャッシュを使用できない場合。
たとえば、データベース管理者がアプリケーションへのパッチの適用中に、結果キャッシュを使用できない状態にした場合などです(「結果がキャッシュされるファンクションが依存するPL/SQLユニットへのホット・パッチの適用」を参照)。
-
結果がキャッシュされるファンクションが依存する表またはビューに対して、セッションがDML文を実行している場合。
このセッションは、そのDML文が完了するまで(コミットまたはロールバックされるまで)そのファンクションの結果キャッシュをバイパスします。その文がロールバックされると、このセッションは、そのファンクションのキャッシュの使用を再開します。
キャッシュをバイパスすると、次のことが保証されます。
-
各セッションのユーザーは、コミットされていないユーザー独自の変更を参照できます。
-
PL/SQLファンクションの結果キャッシュには、すべてのセッションで参照可能なコミットされた変更のみが含まれます。このため、あるセッションでコミットされていない変更は、他のセッションでは参照できません。
-
結果がキャッシュされるファンクションによるセッション固有の設定の処理
セッションによって異なる可能性がある設定(NLS_DATE_FORMAT
やTIME ZONE
など)にファンクションが依存している場合は、様々な設定を処理できるようにそのファンクションを変更できる場合にのみ、そのファンクションの結果がキャッシュされるようにします。
例8–39のファンクションget_hire_date
は、TO_CHAR
ファンクションを使用してDATE
項目をVARCHAR
項目に変換しています。ファンクションget_hire_date
に書式マスクが指定されていないため、書式マスクは、デフォルトでNLS_DATE_FORMAT
に指定されている書式マスクになります。get_hire_date
を起動するセッションのNLS_DATE_FORMAT
設定が異なっている場合、キャッシュされた結果の書式も異なる可能性があります。あるセッションで計算されてキャッシュされた結果がエージ・アウトされ、別のセッションで再計算された場合、同じパラメータ値に対する場合でも、書式が異なる可能性があります。キャッシュされた結果がセッションで取得され、結果の書式がセッションの書式とは異なる場合、その結果は不適切である可能性があります。
この問題の解決方法をいくつか次に示します。
-
get_hire_date
の戻り型をDATE
に変更し、各セッションがTO_CHAR
ファンクションを起動するようにします。 -
ある共通の書式がすべてのセッションで受入れ可能である場合は、書式マスクを指定して、
NLS_DATE_FORMAT
への依存性を削除します。たとえば:TO_CHAR(date_hired, 'mm/dd/yy');
-
書式マスクのパラメータを
get_hire_date
に追加します。たとえば:CREATE OR REPLACE FUNCTION get_hire_date (emp_id NUMBER, fmt VARCHAR) RETURN VARCHAR RESULT_CACHE AUTHID DEFINER IS date_hired DATE; BEGIN SELECT hire_date INTO date_hired FROM HR.EMPLOYEES WHERE EMPLOYEE_ID = emp_id; RETURN TO_CHAR(date_hired, fmt); END; /
例9-41 結果がキャッシュされるファンクションによるセッション固有の設定の処理
CREATE OR REPLACE FUNCTION get_hire_date (emp_id NUMBER) RETURN VARCHAR RESULT_CACHE AUTHID DEFINER IS date_hired DATE; BEGIN SELECT hire_date INTO date_hired FROM HR.EMPLOYEES WHERE EMPLOYEE_ID = emp_id; RETURN TO_CHAR(date_hired); END; /
結果がキャッシュされるファンクションによるセッション固有のアプリケーション・コンテキストの処理
アプリケーション・コンテキストは、グローバルまたはセッション固有のいずれかで、属性とそれらの値の集合のことです。PL/SQLファンクションは、次の1つ以上の項目を実行する場合、セッション固有のアプリケーション・コンテキストに依存します。
-
指定したコンテキストで指定した属性の値を戻すSQLファンクション
SYS_CONTEXT
の直接起動 -
ファイングレイン・セキュリティのための仮想プライベート・データベース(VPD)・メカニズムを使用した
SYS_CONTEXT
の間接起動(VPDの詳細は、『Oracle Databaseセキュリティ・ガイド』を参照してください)
PL/SQLファンクションの結果キャッシュ機能は、セッション固有のアプリケーション・コンテキストへの依存性を自動的には処理しません。セッション固有のアプリケーション・コンテキストに依存しているファンクションの結果をキャッシュする必要がある場合は、アプリケーション・コンテキストをパラメータとしてファンクションに渡す必要があります。このパラメータにはデフォルト値を指定できるため、すべてのユーザーがこのパラメータを指定する必要があるわけではありません。
例9-42では、表config_tab
に、次に示す問合せを変換するVPDポリシーがあると想定しています。
SELECT value FROM config_tab WHERE name = param_name;
この問合せへ:
SELECT value FROM config_tab
WHERE name = param_name
AND app_id = SYS_CONTEXT('Config', 'App_ID');
例9-42 結果がキャッシュされるファンクションによるセッション固有のアプリケーション・コンテキストの処理
CREATE OR REPLACE FUNCTION get_param_value ( param_name VARCHAR, appctx VARCHAR DEFAULT SYS_CONTEXT('Config', 'App_ID') ) RETURN VARCHAR RESULT_CACHE AUTHID DEFINER IS rec VARCHAR(2000); BEGIN SELECT val INTO rec FROM config_tab WHERE name = param_name; RETURN rec; END; /
結果キャッシュの粒度の選択
PL/SQLにはファンクション結果キャッシュが用意されていますが、キャッシュの粒度はユーザーが選択します。粒度の概念を理解するために、Order Entry(OE
)サンプル・スキーマ内のProduct_Descriptions
表について考えてみます。
NAME NULL? TYPE ---------------------- -------- --------------- PRODUCT_ID NOT NULL NUMBER(6) LANGUAGE_ID NOT NULL VARCHAR2(3) TRANSLATED_NAME NOT NULL NVARCHAR2(50) TRANSLATED_DESCRIPTION NOT NULL NVARCHAR2(2000)
この表には、各製品の名前と説明が複数の言語で記載されています。各行の一意のキーは、PRODUCT_ID,LANGUAGE_ID
です。
PRODUCT_ID
およびLANGUAGE_ID
を受け取って、関連付けられたTRANSLATED_NAME
を戻すファンクションを定義する必要があるとします。また、変換された名前をキャッシュする必要もあるとします。これらの名前をキャッシュする場合の粒度の選択肢の一部を次に示します。
-
一度に1つの名前(粒度が細かい)
-
一度に1つの言語(粒度が粗い)
表9-4 粒度が細かいキャッシュと粗いキャッシュ
粒度 | 利点 |
---|---|
細かい |
各ファンクション結果は、1つの論理結果に対応しています。 1回以上必要とされるデータのみを格納します。 各データ項目は、個別にエージ・アウトされます。 バルク・ロードは最適化できません。 |
粗い |
各ファンクション結果には、多数の論理的部分結果が含まれています。 使用されることのないデータを格納する場合もあります。 1つのデータ項目がエージ・アウトされると、全体がエージ・アウトされます。 バルク・ロードを最適化できます。 |
例9-43および例9-44では、ファンクションproductName
がPRODUCT_ID
およびLANGUAGE_ID
を取り、関連付けられたTRANSLATED_NAME
を戻しています。productName
の各バージョンは、変換された名前をキャッシュしますが、キャッシュする際の粒度はそれぞれ異なっています。
例9-43では、get_product_name_1
は結果がキャッシュされるファンクションです。get_product_name_1
は、別のPRODUCT_ID
およびLANGUAGE_ID
で起動されると、常に関連付けられたTRANSLATED_NAME
をキャッシュします。get_product_name_1
が起動されるたびに、最大1つのTRANSLATED_NAME
がキャッシュに追加されます。
例9-44では、get_product_name_2
は、結果がキャッシュされるファンクションall_product_names
を定義します。get_product_name_2
が別のLANGUAGE_ID
でall_product_names
を起動すると、常にall_product_names
はそのLANGUAGE_ID
に関連付けられたすべてのTRANSLATED_NAME
をキャッシュします。all_product_names
が起動されるたびに、最大1つのLANGUAGE_ID
のすべてのTRANSLATED_NAME
がキャッシュに追加されます。
例9-43 一度に1つの名前のキャッシュ(粒度が細かい)
CREATE OR REPLACE FUNCTION get_product_name_1 (
prod_id NUMBER,
lang_id VARCHAR2
)
RETURN NVARCHAR2
RESULT_CACHE
AUTHID DEFINER
IS
result_ VARCHAR2(50);
BEGIN
SELECT translated_name INTO result_
FROM OE.Product_Descriptions
WHERE PRODUCT_ID = prod_id
AND LANGUAGE_ID = lang_id;
RETURN result_;
END;
/
例9-44 一度に1つの言語の変換された名前のキャッシュ(粒度が粗い)
CREATE OR REPLACE FUNCTION get_product_name_2 (
prod_id NUMBER,
lang_id VARCHAR2
)
RETURN NVARCHAR2
AUTHID DEFINER
IS
TYPE product_names IS TABLE OF NVARCHAR2(50) INDEX BY PLS_INTEGER;
FUNCTION all_product_names (lang_id VARCHAR2)
RETURN product_names
RESULT_CACHE
IS
all_names product_names;
BEGIN
FOR c IN (SELECT * FROM OE.Product_Descriptions
WHERE LANGUAGE_ID = lang_id) LOOP
all_names(c.PRODUCT_ID) := c.TRANSLATED_NAME;
END LOOP;
RETURN all_names;
END;
BEGIN
RETURN all_product_names(lang_id)(prod_id);
END;
/
Oracle RAC環境での結果キャッシュ
キャッシュされた結果はシステム・グローバル領域(SGA)に格納されます。Oracle RAC環境では、各データベース・インスタンスによって、そのインスタンス独自のローカルなファンクション結果キャッシュが管理されます。ただし、ローカルな結果キャッシュの内容は、他のOracle RACインスタンスに付随するセッションからアクセスできます。必要な結果がローカル・インスタンスの結果キャッシュから欠落している場合、ローカルで計算するのではなく、他のインスタンスのローカル・キャッシュから結果が取り出される場合があります。インスタンスのアクセス・パターンおよびワークロードによって、そのインスタンスのローカル・キャッシュに格納される結果セットが決まります。このため、インスタンスが異なると、そのローカル・キャッシュに格納される結果セットも異なります。
キャッシュされた結果をリモート・インスタンスからフェッチする前に、データベースはヒューリスティックを使用して、ローカル・インスタンスで結果を再計算するほうが効率的かどうかを判断します。この機能の使用を監視するには、V$RESULT_CACHE_OBJECTS
ビューとV$RESULT_CACHE_STATISTICS
ビューを問い合せます。オブジェクトが別のインスタンスの結果キャッシュからフェッチされた場合、V$RESULT_CACHE_OBJECTS
のGLOBAL
列の値はYesになります。値'No'は、結果がリモートで使用できなかったか、システムがリモートでフェッチするより効率的であると判断したために、結果がローカルで再計算されたことを意味します。V$RESULT_CACHE_STATISTICS
ビューの統計'Global Prune Count'
は、リモート・インスタンスからフェッチしないと決定された回数を示します。'Global Prune By Self Count'
は、インスタンスがローカル結果の提供を要求し、リクエスト元のインスタンスが結果をローカルに計算するほうがより効率的であると判断した回数を示します。最後に、'Global Load Rate'
は、他のインスタンスの結果キャッシュから結果をフェッチする計算速度(10ミリ秒当たりのバイト数)を示します。これらの統計はすべて、RAC環境のグローバル結果キャッシュにのみ適用されます。
各データベース・インスタンスには、そのインスタンス独自のキャッシュされた結果セットが含まれている可能性がありますが、無効な結果を処理するメカニズムはOracle RAC環境全体にわたります。たとえば、データベース表内のデータから計算される品目の価格の結果キャッシュについて考えてみます。ある品目の価格に影響を与える方法でこれらのデータベース表のいずれかが更新された場合、キャッシュされたその品目の価格はOracle RAC環境内のすべてのデータベース・インスタンスで無効になります。
関連項目:
Oracle RACデータベースでの RESULT_CACHE_MAX_SIZE
パラメータおよびその他の初期化パラメータの設定の詳細は、Oracle Real Application Clusters管理およびデプロイメント・ガイドを参照してください
結果キャッシュの管理
PL/SQLファンクション結果キャッシュは、その管理および管理性インフラストラクチャを結果キャッシュと共有します。
DBMS_RESULT_CACHE
サブプログラムを使用して、SQL結果キャッシュおよびPL/SQLファンクション結果キャッシュによって使用される共有プール領域部分を管理できます。DBMS_RESULT_CACHE.BLACKLIST_ADD
プロシージャを使用すると、問合せまたはPL/SQLファンクションをブロックリストに追加して、結果のキャッシュを停止できます。バインド変数または引数のどちらを使用しても、オブジェクトは生成されません。結果キャッシュの行ソースは実行計画に引き続き表示されますが、実行時にはno-opになります。ファンクションに対して何万ものキャッシュ結果の一意の引数が実行されるケースを検索して診断すると、結果キャッシュの問題を解決できます。ワークロードによっては、これらのキャッシュされた結果を管理するオーバーヘッドによって、結果をキャッシュする利点が相殺される場合があります。パフォーマンス・ビューを使用すると、この特別なケースを把握できます。
問合せを実行して、問題のある問合せまたはファンクションを識別できます。cache_id
は、SQLカーソルまたはPL/SQLファンクションの結果キャッシュ識別子です。この問合せは、各キャッシュIDに対して行われた一意の結果キャッシュ・オブジェクトの数をカウントします。一意のバインド変数または引数を持つ問合せまたはファンクションを実行するたびに、一意のオブジェクトが作成されます。
SELECT cache_id, COUNT(cache_key) AS uniq_args
FROM GV$RESULT_CACHE_OBJECTS
WHERE type = 'Result'
GROUP BY cache_id
ORDER BY uniq_args DESC;
依存オブジェクトがワークロードによって頻繁に更新される場合、結果キャッシュを使用することによるパフォーマンス上の利点に悪影響を与える可能性があります。たとえば、大規模なトランザクションがコミットされ、すでにキャッシュされている結果に影響を与える場合、間違った結果を防ぐために、これらのキャッシュされた結果を無効にするメッセージが送信されます。このボトルネックが発生している最初のヒントとして、GV$CHANNEL_WAITS
ビューのCHANNEL = 'Result Cache: Channel'
で高待機が観察されます。問合せを実行してculpritをチェックし、ブロックリストへのオブジェクトの追加などの適切なアクションを実行できます。無効化の数が非常に多いオブジェクトは、この問合せを使用して診断できます。
SELECT object_no, SUM(invalidations) AS num_invals
FROM GV$RESULT_CACHE_OBJECTS
WHERE type = 'Dependency'
GROUP BY object_no
ORDER BY num_invals DESC;
関連項目:
-
DBMS_RESULT_CACHE
パッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください
動的パフォーマンスのビューには、サーバーとクライアントの結果キャッシュを監視するための情報が示されます。
関連項目:
-
結果キャッシュの構成の詳細は、Oracle Databaseパフォーマンス・チューニング・ガイドを参照してください。
-
V$RESULT_CACHE_STATISTICS
の詳細は、『Oracle Databaseリファレンス』を参照してください -
V$RESULT_CACHE_MEMORY
の詳細は、『Oracle Databaseリファレンス』を参照してください -
V$RESULT_CACHE_OBJECTS
の詳細は、『Oracle Databaseリファレンス』を参照してください -
V$RESULT_CACHE_DEPENDENCY
の詳細は、『Oracle Databaseリファレンス』を参照してください
データベース管理者は、結果キャッシュの初期化パラメータを指定して、サーバー結果キャッシュを管理します。
関連項目:
- サーバー結果キャッシュのインフラストラクチャの詳細は、Oracle Database概要を参照してください
結果がキャッシュされるファンクションが依存するPL/SQLユニットへのホット・パッチの適用
結果がキャッシュされるファンクションが依存するPL/SQLユニットに(直接または間接的に)ホット・パッチを適用する際、結果がキャッシュされるファンクションに関連付けられているキャッシュされた結果がすべての場合に自動的にフラッシュされるとはかぎりません。
たとえば、結果がキャッシュされるファンクションP1
.foo()
がパッケージ・サブプログラムP2
.bar()
に依存しているとします。パッケージP2
の本体の新しいバージョンがロードされた場合、P1
.foo()
に関連付けられているキャッシュされた結果は、自動的にはフラッシュされません。
このため、PL/SQLユニットへのホット・パッチの適用には、次の手順を実行することをお薦めします。
ノート:
これらのステップに従うには、DBMS_RESULT_CACHE
パッケージに対するEXECUTE
権限が必要です。