L
o
a
d
i
n
g
.
.
.

ホーム

お知らせ

製品・ソリューション

サービス

導入事例・パートナー

EXEM Academy・ブログ

会社情報

採用情報

2021.12.17

Result Cacheの動作原理と活用方法

Result Cacheの動作原理と活用方法

(株)エクセムコンサルティング本部/DBコンサルティングチームキム・チョルファン

概要

ORACLE DBMSを使用するシステムでは、QUERYパフォーマンスは何よりも重要な要素の1つであり、そのパフォーマンスと直接関連するのがI / Oです。

多くの件数をACCESS しなければ、必要な結果値を得ることができないQUERY を実行すると、BLOCK I/Oが多く発生することになります。 このため、QUERYのパフォーマンスは悪いです。

 コードテーブルのように少ないデータを同時に多くのユーザーが照会する場合は、BUFFER CACHEで希望のBLOCKを見つけて結果を送信しますが、同時に多くのユーザーが使用するためHOT BLOCKになり、ORACLE待機イベントが発生し、速いパフォーマンスを期待することは難しいです。

I / Oに応じてQUERYのパフォーマンスが左右されるため、I / Oを最小限にし、QUERYを実行するとパフォーマンスが向上します。

ORACLE 11GでI/Oの改善のために実装した機能がRESULT CACHE機能です。

RESULT CACHE は SHARED POOL で RESULT CACHE MEMORY と呼ばれる領域に SQL と

PL/SQL FUNCTIONの結果を保存し、以降同じQUERY照会時にRESULT CACHEに格納されているQUERY結果値をそのまま活用する機能です。

繰り返し同じ結果値を照会するQUERYで使用され、多くのデータを処理して少ない結果件数を見たい場合にBLOCK I/Oを発生させずに結果を送信するため、照会パフォーマンスにおいて非常に速い結果が得られます。

これから、RESULT CACHE QUERYの動作原理と設定方法を知り、機能の活用について学びましょう。

RESULT CACHE QUERYの動作原理

通常、QUERYが実行され、BUFFER CACHEに目的のブロックがある場合は、要求されたセッションにブロックを送信します。

BUFFER CACHE領域に存在しない場合は、DISK I / Oが発生した後にBUFFER CACHEにBLOCKを置き、要求されたセッションに結果を送信します。

RESULT CACHE機能は一般的なQUERY動作方式と同じですが、結果の値をCACHINGするという点が異なります。

RESULT CACHE QUERY 最初の実行。

  1. RESULT CACHE QUERYが実行されると、最初にSHARED POOL領域のRESULTCACHE メモリーで OBJECT の CACHING かどうかを確認する。
  2. OBJECTがCACHINGされていない場合は、BUFFER CACHEでBLOCKを探します。
  3. BUFFER CACHE に希望の BLOCK が存在しない場合は DISK から BLOCK を読み込みBUFFER CACHEに送信します。
  4. その結果、値をQUERYしたセッションに送信する
  5.  最後に、RESULT CACHE領域にQUERY結果値を格納します。

RESULT CACHE QUERY 繰り返し実行.

1.     RESULT CACHE QUERYが実行されると、最初にSHARED POOL領域のRESULTCACHE メモリーで OBJECT の CACHING かどうかを確認します。

2.     CACHINGされた情報が存在すれば、I/Oを発生させずにCACHINGされた結果値を要求したセッションに送信します。

RESULT CACHE機能の設定と終了

RESULT CACHE機能の設定

PARAMETER設定でRESULT CACHE機能を使用できます。

 セットアップに必要な主要PARAMETERを見てみましょう。

RESULT_CACHE_MODE

RESULT_CACHE_MODE PARAMETERの値に応じて2つのMODEの設定が可能です。

MANUALの場合は、SQLごとに/*+ RESULT_CACHE */ HINT を与え、

RESULT CACHE 機能が使用可能で FORCE の場合、すべての SQL が RESULT CACHE の

対象となります。

 ただし、/*+ NO_ RESULT_CACHE */ HINT を除く。

 RESULT_CACHE_MODE PARAMETERのDEFAULT値はMANUALです。

RESULT_CACHE_MAX_SIZE               

RESULT CACHE機能を使用するには、RESULT_CACHE_MAX_SIZE値も明示的に指定されていますあるべきです。

このPARAMETERの最大値はSHARED POOLの最大75%まで設定できます。

RESULT_CACHE_MAX_RESULT

1つのSQLに結果セットのキャッシュ領域全体で最大割り当て可能なメモリサイズ。

DEFAULT値は5%です。

RESULT_CACHE_REMOTE_EXPIRATION

REMOTE DATABASE OBJECT の保管周期を時間(分)指定が可能で、DEFAULT値は0です。

The default is 0 which means that resultsets dependant on remote OBJECT

RESULT CACHE機能を終了する

RESULT CACHE機能を取り消す方法には、特定のINSTANCEがRESULT CACHE機能を使用できないように設定する方法とRESULT CACHE機能は使用可能ですが、CACHEでOBJECTを解除する2つの方法があります。

INSTANCEがRESULT CACHE機能を使用したくない場合は、RESULT_CACHE_MODE値を0の値に設定してINSTANCEを再起動するだけです。

RESULT CACHE機能は使用可能ですが、CACHINGされているOBJECTを取り消す方法は、RESULT CACHEパッケージを利用して取り消すことができます。

CACHEで終了する方法については、例を見てみましょう。

CACHINGされたOBJECTを取り消す方法

RESULT CACHE 機能を使用して CACHING された複数の OBJECT のうち、特定の OBJECT のみCACHEで取り消すには、DBMS_RESULT_CACHE.INVALIDATEパッケージを使用して取り消すことができます。

[QUERY 実行] SELECT ID,

TYPE, STATUS, BUCKET_NO, HASH,NAME

FROM   V$RESULT_CACHE_OBJECT;

[結果値]

ID    TYPE STATUS BUCKET_NO HASH     NAME

—– —- ——- ———- ——— —————————-

0 Dependency Published   660 319061 DBAADM.TB_RC_TEST_YYYYMMDD

1 RESULT     Published 2011 159411      SELECT       /*+ RESULT_CACHE */

SUBSTR(SDATE,1,6) SDATE, PROD,

SUM(AMT1) AMT1, SUM(amt2) AMT2, SUM(AMT3) AMT3

FROM         TB_RC_TEST_YYYYMMDD GROUP BY SUBSTR(SDATE,1,6),

PROD

[パッケージの実行]

EXEC DBMS_RESULT_CACHE.INVALIDATE(‘DBAADM’,’ TB_RC_TEST_YYYYMMDD’)

[QUERY 実行] SELECT

ID, TYPE, STATUS,

BUCKET_NO, HASH,NAME

FROM   V$RESULT_CACHE_OBJECT;

[結果値]

no rows selected.

[パッケージの実行]

EXEC DBMS_RESULT_CACHE.FLUSH

[QUERY 実行] SELECT

ID, TYPE, STATUS,

BUCKET_NO, HASH,NAME

FROM  V$RESULT_CACHE_OBJECT;

[結果値]

no rows selected.

RESULT CACHEに登録されているすべてのOBJECTをDBMS_RESULT_CACHE.FLUSHパッケージを介して一括解約できます。

[QUERY 実行]

SELECT /*+ RESULT_CACHE */ 1 FROM DUAL; SELECT /*+ RESULT_CACHE */ 2 FROM DUAL; SELECT /*+ RESULT_CACHE */ 3 FROM DUAL;

[QUERY 実行] SELECT

ID, TYPE, STATUS,

BUCKET_NO, HASH,NAME

FROM   V$RESULT_CACHE_OBJECT;

[結果値]

ID TYPE          STATUS  BUCKET_NO HASH            NAME

— ———-    ——— ——– ——– ————————————-

2 RESULT        Published 3870      83370270 SELECT /*+ RESULT_CACHE */ 3 FROM DUAL

1 RESULT        Published 2222      93590190 SELECT /*+ RESULT_CACHE */ 2 FROM DUAL

0 RESULT        Published 3414      7988310   SELECT /*+ RESULT_CACHE */ 1 FROM DUAL

[パッケージの実行]

EXEC DBMS_RESULT_CACHE.FLUSH

[QUERY 実行] SELECT

ID, TYPE, STATUS,

BUCKET_NO, HASH,NAME

FROM   V$RESULT_CACHE_OBJECT;

[結果値]

no rows selected

RESULT CACHE機能を活用する

過去の顧客会社の例を見ると、オンライン時に商品について実績を見る業務があった。

業績表は1年間保管され、NON PARTITIONされた表が12個存在しています。

特定の月に該当するパフォーマンスを表示するには、そのテーブルにすべてのデータを読み込む必要があります。

 そうなるとI/Oが多く発生し、速い性能が期待できません。

 そこで毎日夜間バッチが実行され、前日基準で実績集計テーブルを更新していました。

多くの改善の効果がありますが、まだ読み取るべきデータが多いため、多くのブロックI/Oが発生しています。

 ここで、各月に対応する実績照会をRESULT CACHE機能を使用する場合、多くのパフォーマンス改善があります。

 特定の月に対応するパフォーマンステストデータを生成して、RESULT CACHE機能を活用してみます。

 テーブル生成スクリプト

[DDLの実行]

CREATE TABLE TB_RC_TEST_YYYYMMDD AS

SELECT

TO_CHAR(ADD_MONTHS(SYSDATE,-1) ,’YYYYMM’)|| TRIM(TO_CHAR(ROUND(DBMS_RANDOM.VALUE(1,31)),’09’))||

TRIM(TO_CHAR(ROUND(DBMS_RANDOM.VALUE(0,23)),’09’))|| TRIM(TO_CHAR(ROUND(DBMS_RANDOM.VALUE(00,59)),’09’)) SDATE, DBMS_RANDOM.STRING(‘U’,2) PROD, ROUND(DBMS_RANDOM.VALUE(100,100000)) AMT1, ROUND(DBMS_RANDOM.VALUE(10,10000)) AMT2, ROUND(DBMS_RANDOM.VALUE(1000,100)) AMT3

FROM   DUAL

CONNECT BY LEVEL <= 10000000 ;

RESULT CACHE機能を使用していない場合(X)

[QUERY 実行] SELECT

SUBSTR(SDATE,1,6) SDATE, PROD,

SUM(AMT1) AMT1, SUM(AMT2) AMT2, SUM(AMT3) AMT3

FROM   TB_RC_TEST_YYYYMMDD GROUP BY SUBSTR(SDATE,1,6),

PROD

[実行計画]

call    count      cpu   elapsed      disk     QUERY   current       rows

——- —— ——– ———- ———- ———- ———-  ———-

Parse10.000.000000
Execute10.000.000000
Fetch4715.6215.8046944469480676

——- —— ——– ———- ———- ———- ———-  ———- total 49           15.62 15.80     46944     46948     0            676

Rows (1st) Row Source OPERATION

———- ————————————————— 676 SORT GROUP BY (cr=46948 pr=46944 pw=0 time=15803245)

10000000 TABLE ACCESS FULL TB_RC_TEST_YYYYMMDD (cr=46948 pr=46944 pw=0 time=3144528)

実施結果を見ると、38,670個のBLOCK I/Oが発生しています。

RESULT CACHE機能を使用してテストをやり直してください。

RESULT CACHE機能を使用した場合(O)(最初の実行)

[QUERY 実行]

SELECT /*+ RESULT_CACHE */ SUBSTR(SDATE,1,6) SDATE, PROD,

SUM(AMT1) AMT1, SUM(AMT2) AMT2, SUM(AMT3) AMT3

FROM   TB_RC_TEST_YYYYMMDD GROUP BY SUBSTR(SDATE,1,6),

PROD

[実行計画]

call    count      cpu   elapsed      disk     QUERY   current       rows

——- —— ——– ———- ———- ———- ———-  ———-

Parse10.000.000000
Execute10.000.000000
Fetch4715.6215.8046944469480676

——- —— ——– ———- ———- ———- ———-  ———- total 49           15.62 15.80     46944     46948     0            676

Rows (1st) Row Source OPERATION

———- ————————————————— 676 SORT GROUP BY (cr=46948 pr=46944 pw=0 time=15803245)

10000000 TABLE ACCESS FULL TB_RC_TEST_YYYYMMDD (cr=46948 pr=46944 pw=0 time=3144528)

行われた結果、依然として38,670個のBLOCK I / Oが発生しています。

最初のQUERY実行時にCACHINGされた領域にOBJECTが存在しなかったからです。 VIEWを見ると、CACHEエリアに登録されていることがわかります。

CACHINGされたOBJECTビュー

[QUERY 実行]

SELECT           ID,

TYPE, STATUS, BUCKET_NO, HASH,

NAME

FROM   V$RESULT_CACHE_OBJECT;

[結果値]

ID       TYPE            STATUS    BUCKET_NO HASH        NAME

—-    —————    ——– ——— ———- ——— ——————-

0     Dependency        Published 660      319061    DBAADM.TB_RC_TEST_YYYYMMDD

1     RESULT            Published 2011      159411    SELECT    /*+ RESULT_CACHE */

これでCACHE登録になっていることを確認したので、もう一度やってみよう。

RESULT CACHE機能を使用した場合(O)(繰り返し実行)

[QUERY 実行]

SELECT /*+ RESULT_CACHE */ SUBSTR(SDATE,1,6) SDATE, PROD,

SUM(AMT1) AMT1, SUM(AMT2) AMT2, SUM(AMT3) AMT3

FROM   TB_RC_TEST_YYYYMMDD GROUP BY SUBSTR(SDATE,1,6),

PROD

[実行計画]

call    count      cpu   elapsed      disk     QUERY   current       rows

——- —— ——– ———- ———- ———- ———-  ———-

Parse10.000.000000
Execute10.000.000000
Fetch470.000.00000676

——- —— ——– ———- ———- ———- ———-  ———- total 49           0.00    0.00      0           0         0         676

Rows (1st) Row Source OPERATION

———- —————————————————

676 RESULT CACHE gnxqgpxppdavj80b6rddg4qsqj (cr=0 pr=0 pw=0 time=20 us)

0 SORT GROUP BY (cr=0 pr=0 pw=0 time=0 )

0   TABLE ACCESS FULL TB_RC_TEST_YYYYMMDD (cr=0 pr=0 pw=0 time=0 )

実行計画を見ると、I / Oはまったく発生しませんせした。

 I / Oがまったく発生しないため、SQLを繰り返し実行する場合でも性能を向上させてくれます。

ここでRESULT CACHEというOPERATIONを見ることができます。

結果の値がCACHINGされたのです。

 INLINE VIEWやWITHステートメントなどのクエリでもRESULT CACHE機能を使用できます。

独立してQUERYブロックにCACHINGが可能だからです。

テストを通し学習しましょう。

 ブル生成スクリプト

[DDLの実行]

CREATE TABLE TB_RC_TEST_SYSDATE AS

SELECT

TO_CHAR(ADD_MONTHS(SYSDATE,-1) ,’YYYYMM’)|| TRIM(TO_CHAR(ROUND(DBMS_RANDOM.VALUE(1,31)),’09’))|| TRIM(TO_CHAR(ROUND(DBMS_RANDOM.VALUE(0,23)),’09’))|| TRIM(TO_CHAR(ROUND(DBMS_RANDOM.VALUE(00,59)),’09’)) SDATE, DBMS_RANDOM.STRING(‘U’,2) PROD, ROUND(DBMS_RANDOM.VALUE(100,100000)) AMT1, ROUND(DBMS_RANDOM.VALUE(10,10000)) AMT2, ROUND(DBMS_RANDOM.VALUE(1000,100)) AMT3

FROM   DUAL

CONNECT BY LEVEL <= 300000 ;

INLINE VIEW と WITH 文の使用例

[INLINE VIEW 사용 QUERY] SELECT SDATE, SUM(SUM_AMT)

FROM ( SELECT    SDATE,

NVL(AMT1,0) + NVL(AMT2,0) + NVL(AMT3,0) SUM_AMT FROM          ( SELECT /*+ RESULT_CACHE */

SUBSTR(SDATE,1,6) SDATE, PROD,

SUM(AMT1) AMT1, SUM(AMT2) AMT2, SUM(AMT3) AMT3

UNION ALL SELECT

FROM    TB_RC_TEST_YYYYMMDD GROUP BY SUBSTR(SDATE,1,6),

PROD )

SUBSTR(SDATE,1,6) SDATE,

SUM(AMT1) + SUM(AMT2) + SUM(AMT3) SUM_AMT

FROM     TB_RC_TEST_SYSDATE WHERE         SDATE < :SDATE GROUP BY SUBSTR(SDATE,1,6),

PROD)

GROUP BY SDATE;

[WITH 文の使用 QUERY]

WITH W_TB_RC_TEST_YYYYMMDD AS

(SELECT SDATE,

NVL(AMT1,0) + NVL(AMT2,0) + NVL(AMT3,0) SUM_AMT FROM ( SELECT /*+ RESULT_CACHE */

SUBSTR(SDATE,1,6) SDATE, PROD,

SUM(AMT1) AMT1, SUM(AMT2) AMT2, SUM(AMT3) AMT3

FROM      TB_RC_TEST_YYYYMMDD GROUP BY SUBSTR(SDATE,1,6),

SELECT

SDATE, SUM(SUM_AMT)

PROD ))

FROM   (SELECT  SDATE,

SUM_AMT

FROM          W_TB_RC_TEST_YYYYMMDD UNION ALL

SELECT   SUBSTR(SDATE,1,6) SDATE,

SUM(AMT1) + SUM(AMT2) + SUM(AMT3) SUM_AMT FROM         TB_RC_TEST_SYSDATE

WHERE    SDATE < :SDATE GROUP BY SUBSTR(SDATE,1,6),

PROD)

GROUP BY SDATE;

[実行計画]

call    count      cpu   elapsed       disk     QUERY   current       rows

——- —— ——– ———- ———- ———- ———-  ———-

Parse10.000.000000
Execute10.000.000000
Fetch20.180.180141302

——- —— ——– ———- ———- ———- ———-  ———- total 4            0.18   0.19      0           1413    0            2

Rows (1st) Row Source OPERATION

———- ————————————————— 2 SORT GROUP BY (cr=1413 pr=0 pw=0 time=188846 )

1352 VIEW (cr=1413 pr=0 pw=0 time=2355 )

1352  UNION-ALL (cr=1413 pr=0 pw=0 time=2230 us)

676   VIEW (cr=0 pr=0 pw=0 time=578 )

676    RESULT CACHE gnxqgpxppdavj80b6rddg4qsqj (cr=0 pr=0 pw=0 time=126 us)

0     SORT GROUP BY (cr=0 pr=0 pw=0 time=0 )

0      TABLE ACCESS FULL TB_RC_TEST_YYYYMMDD (cr=0 pr=0 pw=0 time=0 ) 676      SORT GROUP BY (cr=1413 pr=0 pw=0 time=187432 )

104850    TABLE ACCESS FULL TB_RC_TEST_SYSDATE (cr=1413 pr=0 pw=0 time=57449 )

RESULT CACHEを使用する際の考慮事項

DMLを使用する際の考慮事項

CACHINGされたOBJECTにDML(変更)が発生した場合、変更された時点でRESULT CACHE機能は無効になります。

その理由は、CACHINGされたOBJECTが変更された場合、QUERYの結果値に対する整合性を保証できないためです。

したがって、DMLが多く発生するOBJECTはRESULT CACHE機能を使用しないことをお勧めします。

BINDを使用する際の考慮事項

BIND変数の変更が多いQUERYに対しても非効率が発生します。

以下のテスト結果を見るとBIND変数の値に応じて独立してCACHINGされることがわかります。

そのため、BIND変数が

増えると、特定のQUERYがCACHEの領域をすべて使用し、CACHEしたいそれぞれが

他のクエリによってCACHEの登録と失効が頻繁に発生し、CACHEの効率が低下します。

 同じQUERYBIND変数の値が異なる場合

[QUERY実行] VAR NUM NUMBER; EXEC :NUM := 1;

SELECT /*+ RESULT_CACHE */ ‘CACHING Count’ FROM DUAL WHERE 1 = :NUM;

EXEC :NUM := 2;

SELECT /*+ RESULT_CACHE */ ‘CACHING Count’ FROM DUAL WHERE 1 = :NUM;

EXEC :NUM := 3;

SELECT /*+ RESULT_CACHE */ ‘CACHING Count’ FROM DUAL WHERE 1 = :NUM;

[QUERY 実行] SELECT

ID, TYPE, STATUS,

BUCKET_NO, HASH,NAME

FROM   V$RESULT_CACHE_OBJECT;

[結果値]

ID TYPE   STATUS      BUCKET_NO   HASH        NAME

– —-    ——— ——— ———– ——————————————–

3 RESULT Published18822742746SELECT /*+ RESULT_CACHE */ ‘CACHING Count’ FROM
DUAL WHERE 1 = :A   
2 RESULT Published17147906098SELECT /*+ RESULT_CACHE */ ‘CACHING Count’ FROM
DUAL WHERE 1 = :A   
1 RESULT Published388095977768SELECT /*+ RESULT_CACHE */ ‘CACHING Count’ FROM
DUAL WHERE 1 = :A   
0 RESULT Published315798148181SELECT /*+ RESULT_CACHE */ ‘CACHING Count’ FROM
DUAL WHERE 1 = :A   

 特定のOBJECTを使用する際の考慮事項

以下は、クエリ結果セットをCACHINGできない場合です。

l     一時表または DICTIONARY OBJECT (DBA_*, V$_*, GV$_* など) 参照時

  • シーケンスCURRVALとNEXTVAL COLUMNを呼び出す場合

l     QUERY で SQL 関数を使用する場合- CURRENT_TIMESTAMP、LOCAL_TIMESTAMP、SYS_GUID、SYSDATE、SYSTIMESTAMPなど

結論

既存のQUERYは、I / Oが発生しなければ結果セットを知ることができません。 多くのBLOCKでも、多くのセッションが同時に同じBLOCKを使用する場合、WAIT EVENTが発生します。 これは良い性能を期待するのが難しいが、RESULT CACHE機能を使用すると、I/Oをまったく発生しないという部分において、大幅な性能改善の効果があります。 しかし、その機能の長所と短所をよく知って使用しなければ、システムを安定して使用できるはずです。 また、運用しているシステムを見ると、RESULT CACHE機能を使用できる部分があるでしょう。 この機能を活用してI / O性能をさらに向上させることは、より安定化されて最適化されたシステムに発展することになるでしょう。


PHP Code Snippets Powered By : XYZScripts.com