Result Cache 관련 latch는 result cache 에 데이터가 있고 , 그 상태에서 해당 정보에 접근하기 위하여 획득하여야 한다는 것을 전 포스트에서 확인 할 수 있었다.
이번에는 result cache관련 다른 이벤트인 Enq : RC – Result Cache : Contention에 대해서 확인 해 보도록 하자.
다음 쿼리를 이용하여 Result Cache관련 추가된 이벤트가 무엇이 있는지 확인 할 수 있다.
11:28:50 HR 5036>SELECT name , wait_class , PARAMETER1 ,PARAMETER2 ,PARAMETER3 FROM v$event_name WHERE name like '%Result%' ;
NAME WAIT_CLASS PARAMETER1 PARAMETER2 PARAMETER3 --------------------------------- -------------- --------------- --------------- -------------- enq: RC - Result Cache: Contention Application name|mode chunkNo blockNo
|
해당 enqueue가 몇 번이나 발생 하였는지는 v$enque_stat 뷰를 확인 하면 알 수 있다. 그럼 어떠한 경우에 해당 enqueue의 요청이 있는지 확인해 보도록 하자.
테스트를 위해서 데이터 베이스를 Restart한 후 테스트를 진행 해 보았다.
14:09:23 HR 6805>SELECT * FROM v$result_cache_objects ;
no rows selected
14:09:32 HR 6805>SELECT * FROM v$enqueue_stat WHERE eq_type = 'RC' ;
No rows selected
|
위와 같이 조회를 해 보면 아직 RC enqueue가 사용되지 않음을 확인 할 수 있다.
- Test Case#1
Result cache에 등록된 데이터는 없는 상태이다. 새로운 Result 데이터를 등록해 본 후 Enqueue 요청을 확인해 보자.
14:12:10 HR 6805>select /*+ result_cache */ count(*) from test_rc ;
COUNT(*) ---------- 103
14:12:24 HR 6805>set autotrace on exp stat 14:12:36 HR 6805>select /*+ result_cache */ count(*) from test_rc ;
COUNT(*) ---------- 103
Execution Plan ---------------------------------------------------------- Plan hash value: 1775316367
--------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | --------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 3 (0)| 00:00:01 | | 1 | RESULT CACHE | 3dhb1js3x6ghf0zdkxtn6cwvsp | 2 | SORT AGGREGATE | | 1 | | | | 3 | TABLE ACCESS FULL| TEST_RC | | 103 | 3 (0)| 00:00:01 | ----------------------------------------------------------------------------------
Result Cache Information (identified by operation id): ------------------------------------------------------ 1 - column-count=1; dependencies=(HR.TEST_RC); attributes=(single-row); name="select /*+ result_cache */ count(*) from test_rc "
Note ----- - dynamic sampling used for this statement
Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 0 consistent gets 0 physical reads 0 redo size 419 bytes sent via SQL*Net to client 420 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
14:12:43 HR 6805>SELECT name , type , scan_count , object_no , invalidations FROM v$result_cache_objects ;
NAME TYPE SCAN_COUNT OBJECT_NO INVALIDATIONS ------------------------------ ------------ ------------- ------------ ---------------- HR.TEST_RC Dependency 0 76779 0 select /*+ result_cache */ cou Result 1 0 0 nt(*) from test_rc
14:16:32 HR 6805>SELECT * FROM v$enqueue_stat WHERE eq_type = 'RC' ;
INST_ID EQ_T TOTAL_REQ# TOTAL_WAIT# SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME ------ ------ -------------- ------------- ------------ -------------- ---------------- 1 RC 2 0 2 0 0
|
위의 테스트 결과를 보면 Total_req# 이 2번 있고 Succ_req# 값이 2 이다. 즉 두번의 RC enqueue 요청이 있었고 두번의 요청이 모두 성공적으로 enqueue를 획득 하였다는 뜻이다.
-Test Case#2
latch 와 마찬가지로 result cache관련 조회 시 Enqueue요청이 증가 하는지 확인해 보도록 하자.
14:19:15 HR 6805>select /*+ result_cache */ count(*) from test_rc ; COUNT(*) ---------- 103
Execution Plan ---------------------------------------------------------- Plan hash value: 1775316367
----------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ----------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 3 (0)| 00:00:01 | | 1 | RESULT CACHE | 3dhb1js3x6ghf0zdkxtn6cwvsp | | 2 | SORT AGGREGATE | | 1 | | | | 3 | TABLE ACCESS FULL| TEST_RC | | 103 | 3 (0)| 00:00:01 | -----------------------------------------------------------------------------
Statistics ---------------------------------------------------------- 75 recursive calls 0 db block gets 14 consistent gets 8 physical reads 0 redo size 419 bytes sent via SQL*Net to client 420 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 2 sorts (memory) 0 sorts (disk)
14:21:48 HR 6805>SELECT * FROM v$enqueue_stat WHERE eq_type = 'RC' ;
INST_ID EQ_T TOTAL_REQ# TOTAL_WAIT# SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME ------ ------ -------------- ------------- ------------ -------------- ---------------- 1 RC 2 0 2 0 0
|
Result Cache를 사용할 때는 Enqueue에 대한 요청이 발생하지 않음을 확인 할 수 있다.
-Test Case#3
기존의 Result cache 데이터를 변경하기 위해서 test_rc테이블에 대하여 DML을 발생 시킨 후 RC enqueue가 변화 하는지 확인해 보도록 하자
- Check.sql
SELECT name , type , scan_count , object_no , invalidations FROM v$result_cache_objects ; SELECT * FROM v$enqueue_stat WHERE eq_type = 'RC' ;
|
14:27:02 HR 6805>insert into test_rc values ( 104, 'N 104') ;
1 row created.
14:28:35 HR 6805>@check
NAME TYPE SCAN_COUNT OBJECT_NO INVALIDATIONS ------------------------------ ------------ ------------- ------------ ---------------- HR.TEST_RC Dependency 0 76779 0 select /*+ result_cache */ cou Result 2 0 0 nt(*) from test_rc
INST_ID EQ_T TOTAL_REQ# TOTAL_WAIT# SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME ------ ------ -------------- ------------- ------------ -------------- ---------------- 1 RC 2 0 2 0 0
14:29:53 HR 6805>commit ;
14:30:21 HR 6805>@check
NAME TYPE SCAN_COUNT OBJECT_NO INVALIDATIONS ------------------------------ ------------ ------------- ------------ ---------------- HR.TEST_RC Dependency 0 76779 1 select /*+ result_cache */ cou Result 2 0 0 nt(*) from test_rc
INST_ID EQ_T TOTAL_REQ# TOTAL_WAIT# SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME ------ ------ -------------- ------------- ------------ -------------- ---------------- 1 RC 3 0 3 0 0
|
Result Cache를 Invalidation 시켜 보기 위해서 데이터를 변경 시킨 후에 v$result_cache_objects , v$enqueue_stat뷰를 조회해 보면 Dependency 테이블이 invalidation되면서 RC enqueue 요청이 한번 있었다. 새로운 Result를 Caching 시키기 위해서는 Dependency에 한번 쿼리와 연관된 부분을 참조 하기 위해서 한번 이렇게 두 번의 요청이 있었고 , Dependency 부분에 대한 변경을 가할 경우 RC Enqueue 요청이 한번 있음을 확인 할 수 있다.
- Test Case#3
Dependency 가 존재 하는 상태에서 새로운 쿼리 Result 등록시에 RC Enqueue 요청이 몇 번 일어날까 ?
14:36:32 HR 6805>SELECT /*+ result_cache */ max(empno) FROM test_rc ;
MAX(EMPNO) ------------ 105
Execution Plan ---------------------------------------------------------- Plan hash value: 1775316367
----------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ----------------------------------------------------------------------------- | 0 | SELECT STATEMENT | 1 | 13 | 3 (0)| 00:00:01 | | 1 | RESULT CACHE | 93dajfjcxpd1t5474wnnz6kzjb | 2 | SORT AGGREGATE | 1 | 13 | | | | 3 | TABLE ACCESS FULL| TEST_RC | 104 | 1352 | 3 (0)| 00:00:01 | ------------------------------------------------------------------------------
Result Cache Information (identified by operation id): ------------------------------------------------------ 1 - column-count=1; dependencies=(HR.TEST_RC); attributes=(single-row); name="SELECT /*+ result_cache */ max(empno) FROM test_rc "
Statistics ---------------------------------------------------------- 183 recursive calls 0 db block gets 36 consistent gets 9 physical reads 124 redo size 421 bytes sent via SQL*Net to client 420 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 3 sorts (memory) 0 sorts (disk) 1 rows processed
14:36:35 HR 6805>@check
NAME TYPE SCAN_COUNT OBJECT_NO INVALIDATIONS ------------------------------ ------------ ------------- ------------ ---------------- HR.TEST_RC Dependency 0 76779 1 SELECT /*+ result_cache */ max Result 0 0 0 (empno) FROM test_rc select /*+ result_cache */ cou Result 2 0 0 nt(*) from test_rc
INST_ID EQ_T TOTAL_REQ# TOTAL_WAIT# SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME ------ ------ -------------- ------------- ------------ -------------- ---------------- 1 RC 5 0 5 0 0
|
기존에 Dependency 가 존재 하더라도 두 번의 RC enqueue 요청이 발생 하였다. Dependency의 invalidation 상태를 체크 한 후에 쿼리 Result를 등록 시도 하는 것으로 추정이 된다. 아직 Oracle 11g 관련 문서의 부재로 테스트에 의존 할 수 밖에 없는 상황이라서 확실히 결론을 내리기는 어렵다.
- Test Case#4
RC Enqueue 경합을 발생 시켜서 v$enqueue_stat 뷰 및 세션 10046 Trace이용하여 wait Event를 확인 해 보도록 하자.
서로 다른 세션에서 dml.sql을 수행하게 한 후 10046 Trace 확인
- dml.sql
declare v_cnt number ; begin for i IN 1..100000 LOOP insert into test_rc values ( 105 , 'N 105' ) ; commit ; select /*+ result_cache */ count(*) into v_cnt from test_rc ; delete test_rc where empno = 105 ; commit ; end loop; end; /
|
- Session #1
14:43:26 HR 7940>alter session set events '10046 trace name context forever ,level 12' ; Session altered.
14:43:41 HR 7940>@dml
|
- Session #2
14:44:13 HR 7969>alter session set events '10046 trace name context forever , level 12' ;
Session altered.
14:44:29 HR 7969>@dml
|
- DBA Session
14:46:33 SYS 8037>SELECT * FROM v$lock WHERE type = 'RC'; ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK -------- -------- ---------- ---- ---------- ---------- ---------- ---------- ---------- -------32367818 32367844 170 RC 1 31 6 0 0 0
14:46:35 SYS 8037>/
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK -------- -------- ---------- ---- ---------- ---------- ---------- ---------- --------- -------32367818 32367844 138 RC 2 76779 4 0 0 0
14:48:08 SYS 8037>/
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK -------- -------- ---------- ---- ---------- ---------- ---------- ---------- --------- -------32367818 32367844 138 RC 1 31 6 0 0 0
14:48:27 SYS 8037>/
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK -------- -------- ---------- ---- ---------- ---------- ---------- ---------- --------- -------32367818 32367844 170 RC 1 30 6 0 0 0 3236788C 323678B8 138 RC 1 31 6 0 0 0
14:52:52 SYS 8037>SELECT * FROM v$lock WHERE type = 'RC';
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK -------- -------- ---------- ---- ---------- ---------- ---------- ---------- --------- -------32367818 32367844 138 RC 2 76779 3 0 0 0
14:53:59 SYS 8037>/
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK -------- -------- ---------- ---- ---------- ---------- ---------- ---------- --------- -------32367818 32367844 138 RC 2 76779 4 0 0 0 3236788C 323678B8 170 RC 1 30 4 0 0 0
14:54:33 SYS 8037>/
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK -------- -------- ---------- ---- ---------- ---------- ---------- ---------- --------- -------32367818 32367844 138 RC 2 76779 4 0 0 0 3236788C 323678B8 170 RC 1 31 4 0 0 0
14:55:17 SYS 8037>/ ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK -------- -------- ---------- ---- ---------- ---------- ---------- ---------- --------- -------32367818 32367844 170 RC 1 31 6 0 0 1 3236788C 323678B8 138 RC 1 31 0 4 0 0
|
위와 같이 v$lock 뷰를 조회해 보면 Object id 가 76779(TEST_RC-TABLE) , 30(I_COBJ#-INDEX) , 31(CDEF$-TABLE)에 대한 요청이 발생하고 있다. 이 시점에 v$result_cache_objects뷰를 조회해 보면 동일 SELECT /*+ result_cache */ COUNT(*) FROM TEST_RC 쿼리가 여러 개 등록 됨을 확인 할 수 있다. 즉 하나 하나 새로운 쿼리 Result를 등록하고 사용하고 등록하고 사용하고 하는 것이다.
15:21:20 SYS 8606>@check
NAME TYPE STATUS SCAN_COUNT OBJECT_NO INVALIDATIONS ------------------------------ --------- --------- ---------- ---------- ------------- HR.TEST_RC Dependency Published 0 76779 2298194 SELECT /*+ result_cache */ COU Result Published 0 0 0 NT(*) FROM TEST_RC select /*+ result_cache */ cou Result Invalid 2 0 0 nt(*) from test_rc SELECT /*+ result_cache */ max Result Invalid 0 0 0 (empno) FROM test_rc SELECT /*+ result_cache */ COU Result Invalid 0 0 0 NT(*) FROM TEST_RC .....같은 데이터 생략
32 rows selected.
INST_ID EQ_T TOTAL_REQ# TOTAL_WAIT# SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME ------ ------ -------------- ------------- ------------ -------------- ---------------- 1 RC 10235843 229662 10054184 181655 27890
15:21:45 SYS 8606>set serveroutput on 15:23:33 SYS 8606>exec dbms_result_cache.memory_report(true) ;
R e s u l t C a c h e M e m o r y R e p o r t [Parameters] Block Size = 1K bytes Maximum Cache Size = 3296K bytes (3296 blocks) Maximum Result Size = 164K bytes (164 blocks) [Memory] Total Memory = 103528 bytes [0.112% of the Shared Pool] ... Fixed Memory = 5132 bytes [0.006% of the Shared Pool] ....... Cache Mgr = 108 bytes ....... Memory Mgr = 124 bytes ....... Bloom Fltr = 2K bytes ....... State Objs = 2852 bytes ... Dynamic Memory = 98396 bytes [0.107% of the Shared Pool] ....... Overhead = 65628 bytes ........... Hash Table = 32K bytes (4K buckets) ........... Chunk Ptrs = 12K bytes (3K slots) ........... Chunk Maps = 12K bytes ........... Miscellaneous = 8284 bytes ....... Cache Memory = 32K bytes (32 blocks) ........... Unused Memory = 0 blocks ........... Used Memory = 32 blocks ............... Dependencies = 1 blocks (1 count) ............... Results = 31 blocks ................... SQL = 1 blocks (1 count) ................... Invalid = 30 blocks (30 count)
PL/SQL procedure successfully completed.
15:23:45 SYS 8606>show parameter result_cache_max_size
NAME TYPE VALUE ------------------------------------ ---------------------- ------------------------------ result_cache_max_size big integer 3296K
15:25:09 SYS 8606>SELECT name , GETS ,MISSES ,SPIN_GETS FROM v$latch WHERE name like '%Result%' ;
NAME GETS MISSES SPIN_GETS ------------------------------ ---------- ---------- ---------- Result Cache: Latch 28045823 131600 108373 Result Cache: SO Latch 4 0 0
|
Cache Memory에서 1K사이즈 블록을 32개 사용 중이며, 그 중 1개는 Dependency 정보이고 나머지 31개가 SQL Result 이다. 그 중 현재 사용되는 SQL result가 1개 이고 나머지는 invalid 상태임을 확인 할 수 있다.
이 부분은 전혀 예상하지 못했던 부분이다. 단지 RC enqueue 요청 횟수와 v$lock에서의 정보를 확인 해 보기 위한 테스트 였는데 전혀 뜻밖에 동일 SQL이 invalid 되면서 새로운 데이터가 캐시 되고 사용되고 하는 것을 확인 할 수 있다. 이는 latch 요청 증가를 확인해도 알 수 있다.
- Test Case#5
그럼 왜 ? 동일 SQL을 수행하는데 각각의 쿼리들이 새로 등록이 되고 사용이 되는 것일까 ? 어느 경우 이런 경우가 발생 하는지 확인 해 보도록 하자.
16:04:30 HR 11983>@check
no rows selected
no rows selected
16:04:47 HR 11983>set autotrace on exp stat 16:05:23 HR 11983>select /*+ result_cache */ count(*) from test_rc ;
COUNT(*) ---------- 106
Execution Plan ---------------------------------------------------------- Plan hash value: 1775316367
------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 3 (0)| 00:00:01 | | 1 | RESULT CACHE | 3dhb1js3x6ghf0zdkxtn6cwvsp | | | | | 2 | SORT AGGREGATE | | 1 | | | | 3 | TABLE ACCESS FULL| TEST_RC | 106 | 3 (0)| 00:00:01 | ------------------------------------------------------------------------------------------
Statistics ---------------------------------------------------------- 75 recursive calls 0 db block gets 14 consistent gets 0 physical reads 0 redo size 419 bytes sent via SQL*Net to client 420 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 2 sorts (memory) 0 sorts (disk) 1 rows processed
16:05:32 HR 11983>@check
NAME TYPE STATUS SCAN_COUNT OBJECT_NO INVALIDATIONS ------------------------------ --------- --------- ---------- ---------- ------------- HR.TEST_RC Dependency Published 0 76779 0 select /*+ result_cache */ cou Result Published 1 0 0 nt(*) from test_rc
INST_ID EQ_T TOTAL_REQ# TOTAL_WAIT# SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME ------ ------ -------------- ------------- ------------ -------------- ---------------- 1 RC 2 0 2 0 0
|
정상적으로 하나의 Result 데이터를 로드 하였다. DML을 발생 후 어떠한 변화가 있는지 확인해 보자
16:05:35 HR 11983> insert into test_rc values ( 1000 , 'N1000') ; 1 row created. 16:08:41 HR 11983>commit ; Commit complete. 16:08:44 HR 11983>@check
NAME TYPE STATUS SCAN_COUNT OBJECT_NO INVALIDATIONS ------------------------------ --------- --------- ---------- ---------- ------------- HR.TEST_RC Dependency Published 0 76779 1 select /*+ result_cache */ cou Result Invalid 1 0 0 nt(*) from test_rc
INST_ID EQ_T TOTAL_REQ# TOTAL_WAIT# SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME ------ ------ -------------- ------------- ------------ -------------- ---------------- 1 RC 3 0 3 0 0
|
DML발생 후에도 Result Cache에 데이터는 늘어 나지 않았다. 이 시점에 동일 SQL문을 재 수행 해 보도록 하겠다.
16:09:16 HR 11983>select /*+ result_cache */ count(*) from test_rc ;
COUNT(*) ---------- 107
Execution Plan ---------------------------------------------------------- Plan hash value: 1775316367
------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 3 (0)| 00:00:01 | | 1 | RESULT CACHE | 3dhb1js3x6ghf0zdkxtn6cwvsp | | | | | 2 | SORT AGGREGATE | | 1 | | | | 3 | TABLE ACCESS FULL| TEST_RC | 107 | 3 (0)| 00:00:01 | ------------------------------------------------------------------------------------------
Statistics ---------------------------------------------------------- 1229 recursive calls 10 db block gets 213 consistent gets 13 physical reads 124 redo size 419 bytes sent via SQL*Net to client 420 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 17 sorts (memory) 0 sorts (disk) 1 rows processed
16:10:30 HR 11983>@check
NAME TYPE STATUS SCAN_COUNT OBJECT_NO INVALIDATIONS ------------------------------ --------- --------- ---------- ---------- ------------- HR.TEST_RC Dependency Published 0 76779 1 select /*+ result_cache */ cou Result Published 0 0 0 nt(*) from test_rc select /*+ result_cache */ cou Result Invalid 1 0 0 nt(*) from test_rc
Elapsed: 00:00:00.03
INST_ID EQ_T TOTAL_REQ# TOTAL_WAIT# SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME ------ ------ -------------- ------------- ------------ -------------- ---------------- 1 RC 5 0 5 0 0
16:18:03 SYS >set serveroutput on 16:18:07 SYS >exec dbms_result_cache.memory_report(true);
R e s u l t C a c h e M e m o r y R e p o r t [Parameters] Block Size = 1K bytes Maximum Cache Size = 3296K bytes (3296 blocks) Maximum Result Size = 164K bytes (164 blocks) [Memory] Total Memory = 103528 bytes [0.099% of the Shared Pool] ... Fixed Memory = 5132 bytes [0.005% of the Shared Pool] ....... Cache Mgr = 108 bytes ....... Memory Mgr = 124 bytes ....... Bloom Fltr = 2K bytes ....... State Objs = 2852 bytes ... Dynamic Memory = 98396 bytes [0.094% of the Shared Pool] ....... Overhead = 65628 bytes ........... Hash Table = 32K bytes (4K buckets) ........... Chunk Ptrs = 12K bytes (3K slots) ........... Chunk Maps = 12K bytes ........... Miscellaneous = 8284 bytes ....... Cache Memory = 32K bytes (32 blocks) .......... Unused Memory = 29 blocks ........... Used Memory = 3 blocks ............... Dependencies = 1 blocks (1 count) ............... Results = 2 blocks ................... SQL = 1 blocks (1 count) ................... Invalid = 1 blocks (1 count)
PL/SQL procedure successfully completed.
|
위와 같이 참조 Object가 invalid 된 후 재 수행된 SQL문은 cache id 는 같지만 새로운 메모리 영역을 사용함을 확인 할 수 있다. 마치 동일 SQL이지만 실행 계획이 여러 개 생성 될 경우 Child LCO가 늘어 나는 거 같은 느낌이다. 혹시 library cache 영역과 관계가 있을까 해서 v$sqlarea , v$sql 쿼리를 수행해 보지만 select /*+ result_cache */ count(*) from test_rc 라는 SQL문은 찾아 볼 수 없다. 기존에 SQL 수행 단계에서 library cache영역을 확인하기 전에 Result Cache 영역을 조사하는 로직이 하나 추가된 것으로 추정이 된다. library cache 영역과 별개로 Result Cache영역이 사용되고 있음을 확인 할 수있다.
그럼 SQL Result만 새로 추가 되는 것인지 , 아니면 펑션을 사용하는 Result도 재 등록 되는지 확인해 보도록 하자.
create or replace function f_test_rc return number result_cache as v_cnt number ; begin select count(*) into v_cnt from test_rc ; return v_cnt ; end ;
|
16:27:10 HR 11983>SELECT f_test_rc FROM dual ;
F_TEST_RC ---------- 107
16:27:27 HR 11983>@check
NAME TYPE STATUS SCAN_COUNT OBJECT_NO INVALIDATIONS ------------------------------ --------- --------- ---------- ---------- ------------- HR.F_TEST_RC Dependency Published 0 76788 0 HR.TEST_RC Dependency Published 0 76779 1 "HR"."F_TEST_RC"::8."F_TEST_RC Result Published 0 0 0 "#9689ba467a19cd19 #1 select /*+ result_cache */ cou Result Published 0 0 0 nt(*) from test_rc select /*+ result_cache */ cou Result Invalid 1 0 0 nt(*) from test_rc
INST_ID EQ_T TOTAL_REQ# TOTAL_WAIT# SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME ------ ------ -------------- ------------- ------------ -------------- ---------------- 1 RC 7 0 7 0 0
16:28:24 HR 11983>alter function f_test_rc compile ;
Function altered.
Elapsed: 00:00:00.12
16:29:46 HR 11983>SELECT f_test_rc FROM dual ;
F_TEST_RC ---------- 108
16:29:57 HR 11983>@check
NAME TYPE STATUS SCAN_COUNT OBJECT_NO INVALIDATIONS ------------------------------ --------- --------- ---------- ---------- ------------- HR.F_TEST_RC Dependency Published 0 76788 1 HR.TEST_RC Dependency Published 0 76779 2 "HR"."F_TEST_RC"::8."F_TEST_RC Result Published 0 0 0 "#9689ba467a19cd19 #1 select /*+ result_cache */ cou Result Invalid 1 0 0 nt(*) from test_rc select /*+ result_cache */ cou Result Invalid 0 0 0 nt(*) from test_rc "HR"."F_TEST_RC"::8."F_TEST_RC Result Invalid 0 0 0 "#9689ba467a19cd19 #1
6 rows selected.
INST_ID EQ_T TOTAL_REQ# TOTAL_WAIT# SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME ------ ------ -------------- ------------- ------------ -------------- ---------------- 1 RC 11 0 11 0 0
|
위와 같이 새로이 등록됨을 확인 할 수 있다. Invalidation 되는 경우가 많지 않은 경우에 Result Cache를 사용해야지 그렇지 않을 경우 다른 Result Cache 데이터 까지 age out 되어서 불 필요한 RC enqueue 및 Result Cache latch 경합이 발생할 소지가 높다.
그러면 특정 한 Result를 keep 시키는 명령어는 존재를 할 것인가 ? 아쉽게도 dbms_result_cache 패키지로는 불가능 하다.
여기까지 RC Enqueue 는 Result Cache에 대한 등록 및 변경 작업이 있을 경우 획득하는 lock임을 확인 할 수 있었고, 잦은 DML이 발생하는 테이블에 대해서는 Result Cache를 사용하지 말아야 한다는 것을 테스트를 통해 확인 할 수 있었다.
추후 특정 Result Cache 에 대해서 keep 시킬 수 있는 방법을 알게 된다면 추가 하도록 하겠다.