Result Cache Mode중에서 Force에 대해 알아 보도록 하자. Force모드는 SYSTEM / SESSION 모드 두 개다 사용가능하며 시스템이나 세션에서 Force로 설정 시 해당 DB 또는 세션에서 수행하는 모든 SQL에 대하여 Result Cache에 등록을 하게 된다. 만약 이 모드를 사용하게 된다면 시스템 모드보다는 세션 레벨에서 변경을 한 후에 사용을 하게 될 것으로 예상이 된다.
세션레벨에서 Force 모드로 설정 시 어떤 현상들이 발생하는지 테스트를 통하여 알아 보도록 하자.
- Test Case#1
Force모드로 설정 시 수행하는 모든 SQL에 대하여 결과를 Result Cache에 저장한다고 하는데, 과연 세션에서 수행하는 쿼리들 중에서 캐시 되는 것과 그렇지 않은 것에 대한 확인해 보도록 하자.
- Session#1 09:24:37 HR 16592>show parameter result_cache_mode NAME TYPE VALUE ------------------------------------ ---------------------- ------------------------------ result_cache_mode string MANUAL 09:24:56 HR 16592>alter session set result_cache_mode=force ; Session altered. 09:25:12 HR 16592>show parameter result_cache_mode NAME TYPE VALUE ------------------------------------ ---------------------- ------------------------------ result_cache_mode string FORCE 09:25:20 HR 16592>SELECT * FROM tab ; TNAME TABTYPE CLUSTERID ------------------------------------------------------------ -------------- ---------- BIN$RV9LXwCW+D/gQAB/AQAiFQ==$0 TABLE BIN$RWJqIyy8oSngQAB/AQBQbA==$0 TABLE BIN$RdlSlMkfKOvgQAB/AQATOg==$0 TABLE COUNTRIES TABLE DEPARTMENTS TABLE EMPLOYEES TABLE EMP_DETAILS_VIEW VIEW JOBS TABLE JOB_HISTORY TABLE LOCATIONS TABLE REGIONS TABLE TEST_RC TABLE V_EMP VIEW XTOOL_PLAN_TABLE TABLE 14 rows selected. 09:26:14 HR 16592>SELECT cache_id , type , namespace, name , status , scan_count FROM v$result_cache_objects; no rows selected 09:31:05 HR 16592>SELECT max(salary) FROM employees ; MAX(SALARY) ----------- 24000 09:31:33 HR 16592>SELECT cache_id , type , namespace, name , status , scan_count FROM v$result_cache_objects; CACHE_ID TYPE NAMESPACE NAME STATUS SCAN_COUNT -------------------------- ------------ ---------- ----------------------------------- ------------ ---------- HR.EMPLOYEES Dependency HR.EMPLOYEES Published 0 f4cg36a3s8cm34yrg5nwtxug1h Result SQL SELECT max(salary) FROM employees Published 0 09:33:51 HR 16592>SELECT to_char(sysdate,'yyyymmdd') FROM dual ; TO_CHAR(SYSDATE, ---------------- 20080215 09:36:39 HR 16592>SELECT cache_id , type , namespace, name , status , scan_count FROM v$result_cache_objects; CACHE_ID TYPE NAMESPACE NAME STATUS SCAN_COUNT -------------------------- ------------ ---------- ----------------------------------- ------------ ---------- HR.EMPLOYEES Dependency HR.EMPLOYEES Published 0 f4cg36a3s8cm34yrg5nwtxug1h Result SQL SELECT max(salary) FROM employees Published 0 |
위의 몇 가지 간단한 테스트를 진행해 보았다. 테스트 결과에서 알 수 있듯이 Tab , dual , v$result_cache_objects에 대하여 조회하는 쿼리에 대해서는 Result Cache에 등록이 되지 않음을 확인 할 수 있다. 즉, Result Cache에 모든 SQL 결과를 등록시킬 수 있는 것은 아니다.
다음은 Result Cache에 등록 시킬 수 없는 쿼리에 대한 내용이다.
1. Dictionary and temporary tables
2. Sequence CURRVAL and NEXTVAL pseudo columns
3. SQL functions current_date, current_timestamp, local_timestamp, userenv/sys_context (with non-constant variables), sys_guid, sysdate, and sys_timestamp
4. Non-deterministic PL/SQL functions
다음은 Result Cache에 같이 저장되는 파라메터 내용이다.
1. Bind variables.
2. The following SQL functions: dbtimezone, sessiontimezone, userenv/sys_context (with constant variables), uid, and user.
3. NLS parameters.
동일 SQL이지만 바인드 변수가 틀리거나 세션의 NLS 값이 틀리거나 하면 기존에 등록되어 있는 Query Result를 사용하지 못하고 새로이 등록을 하게 된다.
- Test Case#2
하나의 세션에서 FORCE 모드로 등록한 Result Cache를 다른 세션에서 공유해서 사용 가능한지 여부에 대한 테스트
TestCase#1에서의 테스트 세션에 추가적으로 세션 하나를 더 접속시킨 후 테스트를 수행해 보자. 현재 Session#1은 계속해서 접속 중임.
- Session#1은 계속해서 접속 중임 - Session#2 09:49:38 HR 16708>show parameter result_cache_mode NAME TYPE VALUE ------------------------------------ ---------------------- ------------------------------ result_cache_mode string MANUAL 10:03:43 HR 16708>set autotrace traceonly exp stat 10:04:06 HR 16708>SELECT max(salary) FROM employees ; Execution Plan ---------------------------------------------------------- Plan hash value: 1756381138 -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 4 | 3 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 4 | | | | 2 | TABLE ACCESS FULL| EMPLOYEES | 107 | 428 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 7 consistent gets 0 physical reads 0 redo size 422 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 10:07:24 HR 16708>SELECT cache_id , type , namespace, name , status , scan_count FROM v$result_cache_objects; CACHE_ID TYPE NAMESPACE NAME STATUS SCAN_COUNT -------------------------- ------------ ---------- ----------------------------------- ------------ ---------- HR.EMPLOYEES Dependency HR.EMPLOYEES Published 0 f4cg36a3s8cm34yrg5nwtxug1h Result SQL SELECT max(salary) FROM employees Published 0 |
위의 테스트 결과를 확인 해 보면 Session#1에서 등록시켜 놓은 SELECT max(salary) FROM employees 라는 쿼리 결과가 Result Cache에 존재 하고 있다. 하지만 Session#2에서는 Session#1에서 등록시켜 놓은 쿼리를 재 사용하지 못하고 있다. Session#2의 Result Cache Mode가 Manual 이므로 Result Cache에 Manual로 등록된 쿼리가 없어서 사용을 하지 못하고 있는 듯 하다. 다음 테스트를 확인해 보면 실제 Result Cache에 대한 엑세스 자체가 일어 나지 않는다.
- Session#2 10:07:27 HR 16708>SELECT NAME , GETS FROM v$latch WHERE name like 'Result%' ; NAME GETS ----------------------------------- ---------- Result Cache: Latch 18 Result Cache: SO Latch 1 10:08:19 HR 16708>SELECT max(salary) FROM employees ; MAX(SALARY) ----------- 24000 10:08:30 HR 16708>SELECT NAME , GETS FROM v$latch WHERE name like 'Result%' ; NAME GETS ----------------------------------- ---------- Result Cache: Latch 18 Result Cache: SO Latch 1 |
그럼, Session#2에서 Manual로 하나의 Result 값을 등록한 후에는 어떤 변화가 있을까 ? 테스트를 통해 확인해 보자.
- Session#2 10:16:38 HR 16708>SELECT /*+ result_cache */ * FROM departments ; 결과 생략.. 10:17:07 HR 16708>SELECT cache_id , type , namespace, name , status , scan_count FROM v$result_cache_objects; CACHE_ID TYPE NAMESPACE NAME STATUS SCAN_COUNT -------------------------- ------------ ---------- ----------------------------------- ------------ ---------- HR.DEPARTMENTS Dependency HR.DEPARTMENTS Published 0 HR.EMPLOYEES Dependency HR.EMPLOYEES Published 0 ggq8ztnxqw8ft4ucg3art21sjm Result SQL SELECT /*+ result_cache */ * FROM d Published 0 epartments f4cg36a3s8cm34yrg5nwtxug1h Result SQL SELECT max(salary) FROM employees Published 0 10:18:14 HR 16708>SELECT NAME , GETS FROM v$latch WHERE name like 'Result%' ; NAME GETS ----------------------------------- ---------- Result Cache: Latch 25 Result Cache: SO Latch 2 10:18:17 HR 16708>SELECT max(salary) FROM employees ; -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 4 | 3 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 4 | | | | 2 | TABLE ACCESS FULL| EMPLOYEES | 107 | 428 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 7 consistent gets 0 physical reads 0 redo size 422 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 10:18:33 HR 16708>SELECT NAME , GETS FROM v$latch WHERE name like 'Result%' ; NAME GETS ----------------------------------- ---------- Result Cache: Latch 25 Result Cache: SO Latch 2 |
여전히 Force로 설정된 세션에서 등록한 Query Result에 대하여 재 사용을 못하고 있다. 그럼 Session#2의 Result Cache Mode를 Force로 변경해 보도록 하자.
- Session#2 10:19:25 HR 16708>alter session set result_cache_mode=force ; Session altered. 10:25:25 HR 16708>SELECT cache_id , type , namespace, name , status , scan_count FROM v$result_cache_objects; CACHE_ID TYPE NAMESPACE NAME STATUS SCAN_COUNT -------------------------- ------------ ---------- ----------------------------------- ------------ ---------- HR.DEPARTMENTS Dependency HR.DEPARTMENTS Published 0 HR.EMPLOYEES Dependency HR.EMPLOYEES Published 0 0y8dgk314f9f8bz05qsrrny8u8 Result SQL SELECT DECODE('A','A','1','2') FROM Published 1 DUAL ggq8ztnxqw8ft4ucg3art21sjm Result SQL SELECT /*+ result_cache */ * FROM d Published 0 epartments f4cg36a3s8cm34yrg5nwtxug1h Result SQL SELECT max(salary) FROM employees Published 0 10:27:12 HR 16708>SELECT max(salary) FROM employees ; MAX(SALARY) ----------- 24000 10:28:03 HR 16708>SELECT cache_id , type , namespace, name , status , scan_count FROM v$result_cache_objects; CACHE_ID TYPE NAMESPACE NAME STATUS SCAN_COUNT -------------------------- ------------ ---------- ----------------------------------- ------------ ---------- HR.DEPARTMENTS Dependency HR.DEPARTMENTS Published 0 HR.EMPLOYEES Dependency HR.EMPLOYEES Published 0 f4cg36a3s8cm34yrg5nwtxug1h Result SQL SELECT max(salary) FROM employees Published 1 0y8dgk314f9f8bz05qsrrny8u8 Result SQL SELECT DECODE('A','A','1','2') FROM Published 3 DUAL ggq8ztnxqw8ft4ucg3art21sjm Result SQL SELECT /*+ result_cache */ * FROM d Published 0 epartments 10:30:15 HR 16708>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 = 1536K bytes (1536 blocks) Maximum Result Size = 76K bytes (76 blocks) [Memory] Total Memory = 103528 bytes [0.060% of the Shared Pool] ... Fixed Memory = 5132 bytes [0.003% 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.057% 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 = 27 blocks ........... Used Memory = 5 blocks ............... Dependencies = 2 blocks (2 count) ............... Results = 3 blocks ................... SQL = 3 blocks (3 count) |
Session#2를 Force로 설정하였을 경우 Session#1에서 등록한 Query Result에 대해서 재 사용함을 확인 할 수 있다. Sesion#2를 Auto 모드로 변경 시에는 어떤 결과가 나타날지 테스트를 통하여 확인해 보도록 하자.
- Session#2 10:46:48 HR 16708>alter session set result_cache_mode=auto ; Session altered. 10:47:10 HR 16708>show parameter result_cache_mode NAME TYPE VALUE ------------------------------------ ------------ ------------------------------ result_cache_mode string AUTO 10:47:18 HR 16708>SELECT NAME , GETS FROM v$latch WHERE name like 'Result%' ; NAME GETS ----------------------------------- ---------- Result Cache: Latch 48 Result Cache: SO Latch 2 10:47:37 HR 16708>set autotrace on exp 10:47:56 HR 16708>SELECT max(salary) FROM employees ; MAX(SALARY) ----------- 24000 Execution Plan ---------------------------------------------------------- Plan hash value: 1756381138 -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 4 | 3 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 4 | | | | 2 | TABLE ACCESS FULL| EMPLOYEES | 107 | 428 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------------- 10:48:05 HR 16708>SELECT NAME , GETS FROM v$latch WHERE name like 'Result%' ; NAME GETS ----------------------------------- ---------- Result Cache: Latch 48 Result Cache: SO Latch 2 |
역시나 Query Result가 재 사용되지 않았다.
- 요약
FORCE 모드로 설정 시 세션 또는 DB 레벨에서 수행되는 SQL에 대하여 Result Cache에 등록이 되고 사용이 됨을 확인 할 수 있었다. Dictionary 조회나 기타 몇 가지 경우를 제외하고 말이다.
그리고 그것보다 더 중요한 사실은 Result Cache에 등록되어 Query Result와 동일한 Result_Cache_Mode값이 설정이 되어 있어야지만 Query Result를 재 사용한다는 것을 확인 할 수 있었다.
이는 매우 중요한 사실이다. 아무리 많은 Query Result가 Result Cache에 등록이 되어 있다 하더라도 등록 당시와 같은 Result_Cache_Mode로 설정이 되지 않는다면 해당 값을 사용할 수 없게 되기 때문이다.
이런 이유로 개인적으로 판단해 보건 데 Force 모드나 Auto모드 보다는 기본값인 Manual 모드를 많이 사용할 것으로 생각이 된다.