Oracle 从11g开始引入了结果集缓存(result cache)的新特性,用于存储经常使用的SQL语句和函数的查询结果,将来语句再执行的时候,oracle直接的访问内存得到结果。其优点是重用相同的结果集,减少逻辑IO,提高系统性能。Oracle提供了三种结果集缓存,包括:服务器查询结果集缓存、pl/sql函数结果集缓存和客户端结果集缓存。
哪些场景适用?在访问多行返回少数行的语句,典型OLTP等系统的功能;ORACLE建议应用仅仅对read only的表中使用result cache缓存功能。若sql中对应的对象(比如表)做了update,insert,delete或是ddl操作,相关所有sql的缓存结果集就自动失效了,重新刷新结果集缓存。所以result cache只有对那些在平时几乎没有任何DML的只读表比较有用,可以减轻io的压力。
sql中通过/*+ result_cache*/提示实现result cache,pl/sql函数通过建函数时的result_cache子句实现。
使用限制:
(1)查询使用非确定性的函数,序列和临时表的结果集不会被缓存
(2)查询违反了读一致性时结果集将不会被缓存
(3)引用数据字典视图的查询的结果集不会被缓存
(4)查询结果集大于可用缓存结果集可用空间的不被缓存;采用LRU算法来管理result cache。
设置SQL查询结果高速缓存
查询优化程序根据初始化参数文件中RESULT_CACHE_MODE 参数的设置管理结果高速缓存机制。
可以使用此参数确定优化程序是否将查询结果自动发送到结果高速缓存中。可以在系统和会话级别设置RESULT_CACHE_MODE 参数。
参数值可以是AUTO、MANUAL 和FORCE:
(1) 设置为AUTO 时,优化程序将根据重复的执行操作确定将哪些结果存储在高速缓存中。
(2) 设置为MANUAL(默认值)时,必须使用RESULT_CACHE 提示指定在高速缓存中存储特定结果。
(3) 设置为FORCE 时,所有结果都将存储在高速缓存中。
注:对于AUTO 和FORCE 设置,如果语句中包含[NO_]RESULT_CACHE 提示,则该提示优先于参数设置。
与result cache相关的参数 :
result_cache_max_size:result cache是SGA share pool的一部分,由参数result_cache_max_size控制其大小,默认memory_target的0.25%或者sga_target的0.5%或者shared_pool_size的1%,但最大不能超过share pool的75%。
result_cache_max_reslut: 默认5,即5%,单条sql查询结果最大占用result_cache_max_size的比例。
result_cache_remote_expiration:默认0,指定远程数据库中查询结果涉及的表保证多久不变的时间,此参数一般只适合用于只读的表或周期性更改的表,否则会影响本地库调用时的正确性。
查看SQL结果高速缓存字典信息
(G)V$RESULT_CACHE_STATISTICS : 列出各种高速缓存设置和内存使用量统计信息
(G)V$RESULT_CACHE_MEMORY : 列出所有内存块和相应的统计信息
(G)V$RESULT_CACHE_OBJECTS: 列出所有对象(高速缓存结果和依赖性)及其属性
(G)V$RESULT_CACHE_DEPENDENCY: 列出高速缓存结果之间的依赖性详细信息及依赖性
dbms_result_cache包可以监视和管理result cache
例如:dbms_result_cache.flush:清除result cache。
dbms_result_cache.invalidate(owner,name):使某对象的result cache无效。
dbms_result_cache.status:显示result cache的状态。
dbms_result_cache.memory_report:显示result cache的内存使用状况。
下面做一个测试:
SQL> conn l5m/l5m
Connected.
SQL> show parameter result_cache
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
client_result_cache_lag big integer 3000
client_result_cache_size big integer 0
result_cache_max_result integer 5
result_cache_max_size big integer 1536K
result_cache_mode string MANUAL
result_cache_remote_expiration integer 0
SQL> create table rc_test as select * from all_objects;
Table created.
SQL> alter system flush SHARED_POOL;
System altered.
测试数据建好之后,运行一条sql,要保证结果集比较小,因为result_chche_max_size只有1536K。
SQL> set autot trace
SQL> select /*+ result_cache */ owner,sum(data_object_id) from rc_test group by owner order by owner;
25 rows selected.
Elapsed: 00:00:00.13
Execution Plan
----------------------------------------------------------
Plan hash value: 1499524372
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 69059 | 2023K| 294 (2)| 00:00:04 |
| 1 | RESULT CACHE | as34dsjm3wkff7y6tbbuugqb6j | | | | |
| 2 | SORT GROUP BY | | 69059 | 2023K| 294 (2)| 00:00:04 |
| 3 | TABLE ACCESS FULL| RC_TEST | 69059 | 2023K| 291 (1)| 00:00:04 |
--------------------------------------------------------------------------------------------------
Result Cache Information (identified by operation id):
------------------------------------------------------
1 - column-count=2; dependencies=(L5M.RC_TEST); parameters=(nls); name="select /*+ result_cache */ owner,sum(data_obj
ect_id) from rc_test group by owner order by owner"
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
5 recursive calls
0 db block gets
1105 consistent gets
1038 physical reads
0 redo size
1237 bytes sent via SQL*Net to client
534 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
25 rows processed
SQL> set serveroutput on ;
SQL> exec dbms_result_cache.memory_report;
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 = 163944 bytes [0.083% of the Shared Pool]
... Fixed Memory = 5352 bytes [0.003% of the Shared Pool]
... Dynamic Memory = 158592 bytes [0.080% of the Shared Pool]
....... Overhead = 125824 bytes
....... Cache Memory = 32K bytes (32 blocks)
........... Unused Memory = 30 blocks
........... Used Memory = 2 blocks
............... Dependencies = 1 blocks (1 count)
............... Results = 1 blocks
................... SQL = 1 blocks (1 count)
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.07
从sql的执行看,多了“RESULT CACHE | as34dsjm3wkff7y6tbbuugqb6j”的这一条,说明已将些sql的结果集存储在result cache中了。通过dbms_result_cache.memory_report可查看更加详细的信息。
GV$RESULT_CACHE_OBJECTS可以查看到存在result cache的对象信息。
SQL> select cache_id,lru_number,status,bucket_no,hash,name,namespace,type,status
2 from GV$RESULT_CACHE_OBJECTS where name like '%rc_test%';
CACHE_ID LRU_NUMBER STATUS BUCKET_NO HASH NAME NAMESPACE TYPE STATUS
-------------------- ---------- --------------- --------- --------------------- ---------------------------------------- ---------- ---------- ---------------
as34dsjm3wkff7y6tbbu 2 Published 1644 3995117164 select /*+ result_cache */ owner,sum(dat SQL Result Published
ugqb6j a_object_id) from rc_test group by owner
order by owner
通过DBMS_RESULT_CACHE.INVALIDATE将此result cache失效。
SQL> exec DBMS_RESULT_CACHE.INVALIDATE('L5M','RC_TEST');
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00
SQL> select cache_id,lru_number,status,bucket_no,hash,name,namespace,type,status
2 from GV$RESULT_CACHE_OBJECTS where name like '%rc_test%';
CACHE_ID LRU_NUMBER STATUS BUCKET_NO HASH NAME NAMESPACE TYPE STATUS
-------------------- ---------- --------------- --------- --------------------- ---------------------------------------- ---------- ---------- ---------------
as34dsjm3wkff7y6tbbu 0 Invalid 1644 3995117164 select /*+ result_cache */ owner,sum(dat SQL Result Invalid
ugqb6j a_object_id) from rc_test group by owner
order by owner
将此result cache设置为invalid后,如果再运行一次这个sql会怎么样?
SQL> select /*+ result_cache */ owner,sum(data_object_id) from rc_test group by owner order by owner;
25 rows selected.
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
Plan hash value: 1499524372
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 69059 | 2023K| 294 (2)| 00:00:04 |
| 1 | RESULT CACHE | as34dsjm3wkff7y6tbbuugqb6j | | | | |
| 2 | SORT GROUP BY | | 69059 | 2023K| 294 (2)| 00:00:04 |
| 3 | TABLE ACCESS FULL| RC_TEST | 69059 | 2023K| 291 (1)| 00:00:04 |
--------------------------------------------------------------------------------------------------
SQL> set autot off
SQL> select id,cache_id,lru_number,status,bucket_no,hash,name,namespace,type,status
2 from GV$RESULT_CACHE_OBJECTS where name like '%rc_test%';
ID CACHE_ID LRU_NUMBER STATUS BUCKET_NO HASH NAME NAMESPACE TYPE STATUS
--- -------------------- ---------- --------------- --------- --------------------- ---------------------------------------- ---------- ---------- ---------------
2 as34dsjm3wkff7y6tbbu 3 Published 1644 3995117164 select /*+ result_cache */ owner,sum(dat SQL Result Published
ugqb6j a_object_id) from rc_test group by owner
order by owner
1 as34dsjm3wkff7y6tbbu 0 Invalid 1644 3995117164 select /*+ result_cache */ owner,sum(dat SQL Result Invalid
ugqb6j a_object_id) from rc_test group by owner
order by owner
重新运行一次后,发现在result cache中又增加了一笔新的记录,状态是Published,觉得人为的将对象的cache result设为invalid的作用不大,设为Invalid是让oracle知道与此object关连的所有result cache都失效了,下次需要重新生成信息。
通过EXECUTE DBMS_RESULT_CACHE.FLUSH清空所有的result cache:
SQL> EXECUTE DBMS_RESULT_CACHE.FLUSH;
PL/SQL procedure successfully completed.
SQL> select * from GV$RESULT_CACHE_OBJECTS;
no rows selected
参考:https://blog.csdn.net/tianlesoftware/article/details/8271308