2012年3月30日金曜日

[Oracle]ストアドファンクションの結果キャッシュ

ファンクションの結果キャッシュはOracle11gからの新機能で、この機能を使用すると同一のパラメータでストアドファンクションを呼び出した場合、2回目以降はキャッシュから結果を取り出してくれるので処理を高速化できる便利な機能。

細かい使い方は、マニュアルを見よう。

キャッシュを使った場合と使わなかった場合の性能差

実際にキャッシュを使った場合にどのぐらいパフォーマンス的に有利になるのかを測ってみました。

PL/SQLのコード

キャッシュを有効化するには、以下のようにファンクションの定義時に「RESULT_CACHE」キーワードを指定してあげるだけです。

処理的には、TEST_TABELEからパラメータで指定された値に紐付く「VAL」を取得して、返却するだけの簡単な処理になっています。
あと、ほんとに処理がスキップされて結果を返すかを確認するためにDBMS_OUTPUT.PUT_LINEでパラメータを出力してみてます。
CREATE OR REPLACE FUNCTION GET_VAL(key IN CHAR) RETURN CHAR RESULT_CACHE RELIES_ON (TEST_TABLE, HOGE)
AS
    val NVARCHAR2(100);
BEGIN
    DBMS_OUTPUT.PUT_LINE('param = ' || key);
    SELECT VAL INTO val
      FROM TEST_TABLE
     WHERE PK = key;
    RETURN val;
END;
/

テーブルの内容

PK   VAL
---- -----------
'01' 'あいうえお
'02' 'かきくけこ
'03' 'さしすせそ

sqlplusで2回連続で実行してみた

1回目の実行では、パラメータ情報が出力されているけど2回目は出力されていない。
どうやらキャッシュがちゃんと有効になっているっぽい。
19:52:02 SQL> exec :val := get_val('01');
param = 01

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.00
19:52:05 SQL> exec :val := get_val('01');

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.01

参照してるTEST_TABLEに変更加えた場合ってどう動くんだろう?といことで試してみた。
結果だけ見ると、参照テーブルに変更入るとキャッシュが無効化されて最新情報を取りに行くようですね。
20:00:19 SQL> exec :val := get_val('01');

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.00
20:00:23 SQL> update test_table set val = 'hoge' where pk = '01';

1行が更新されました。

経過: 00:00:00.00
20:00:29 SQL> commit;

コミットが完了しました。

経過: 00:00:00.00
20:00:31 SQL> exec :val := get_val('01');
param = 01

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.00

次は、関係ないテーブルに変更加えてみるとどうだろう。
結果、関係ないテーブルの変更はキャッシュに影響は与えないみたいなので想定通りの動き。
20:02:05 SQL> exec :val := get_val('01');

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.00
20:08:17 SQL> update hoge set col1 = '1';

1行が更新されました。

経過: 00:00:00.00
20:08:21 SQL> commit;

コミットが完了しました。

経過: 00:00:00.00
20:08:24 SQL> exec :val := get_val('01');

PL/SQLプロシージャが正常に完了しました。

おわり。