result cache是oracle 11g新推出的特性,通过把查询结果缓存在内存中来提高查询性能。缓存分为clinet和server端缓存。本文主要讨论server端缓存。server result cache是shared pool的内存的一部分。结果缓存更适合于数据变化不频繁的系统,例如OLAP。简单原理如下:当sql执行时,数据库先去result cache去查找相关结果;当结果相关的对象发生变化,例如相关表的数据被删除一条,则结果缓存失效。
SQL> show parameter result
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 85024K
result_cache_mode string FORCE
result_cache_remote_expiration integer 0
SQL>
关于Server Result Cache的几个重要参数
result_cache_mode:
该参数是最为重要的,其属性有manual和force,auto三种。
manual是默认属性,也就是说我们要启用该特性,那么必须通过hint来实现,不然oracle的优化器是无法认知的,oracle关于result cache的
hint如下:
SQL> SELECT name,version FROM v$sql_hint WHERE name LIKE '%RESULT%';
NAME VERSION
---------------------------------------------------------------- -------------------------
RESULT_CACHE 11.1.0.6
NO_RESULT_CACHE 11.1.0.6
当设置为force时,oracle 优化就能自动识别了,不需要使用hint,相反,如果当设置为force时,同时
你又不想某个sql或应用使用该特性,那么可以使用NO_RESUIT_CACHE hint来进行避规。
当设置了auto时,优化器将根据大量因素决定是否缓存结果。决定因素包括查询执行的频率、生成结果的
成本以及针对底层数据库对象更改的频率,目前的稳定性还需要验证。
result_cache_max_size
该参数控制着使用该特性的内存大小,当该参数设置为0,那么也就意味着关闭了该特性。
该部分内存是从SGA中分配的,Oracle11g都不会将RESULT_CACHE_MAX_SIZE设置为超过
SHARED_POOL_SIZE的75%,至于分配的比例关系,metalink提供了如下的数据:
0.25% of MEMORY_TARGET or
0.5% of SGA_TARGET or
1% of SHARED_POOL_SIZE
result_cache_max_result
该参数是控制单个result所能占据query cache的大小比例,注意是一个百分比。
该参数默认是是5%,取值范围当然是1% ~ 100% 了。
result_cache_remote_expiration
该参数的作用是根据远程数据库对象设置缓存过期的时间,默认值为0.
也就是说,默认情况下,远程数据库对象不会被进行cache的。
_result_cache_global
顾名思义,该参数肯定是针对Rac集群而设计的,这样可以大大的降低经典的gc等待。
和Result Cache相关的视图
SQL> select * from dict where table_name like '%RESULT_CACHE%';
TABLE_NAME COMMENTS
------------------------------ --------------------------------------------------------------------------------
CLIENT_RESULT_CACHE_STATS$ Synonym for CRCSTATS_$
GV$RESULT_CACHE_DEPENDENCY Synonym for GV_$RESULT_CACHE_DEPENDENCY
GV$RESULT_CACHE_MEMORY Synonym for GV_$RESULT_CACHE_MEMORY
GV$RESULT_CACHE_OBJECTS Synonym for GV_$RESULT_CACHE_OBJECTS
GV$RESULT_CACHE_STATISTICS Synonym for GV_$RESULT_CACHE_STATISTICS
V$RESULT_CACHE_DEPENDENCY Synonym for V_$RESULT_CACHE_DEPENDENCY
V$RESULT_CACHE_MEMORY Synonym for V_$RESULT_CACHE_MEMORY
V$RESULT_CACHE_OBJECTS Synonym for V_$RESULT_CACHE_OBJECTS
V$RESULT_CACHE_STATISTICS Synonym for V_$RESULT_CACHE_STATISTICS
9 rows
SQL>
V$RESULT_CACHE_STATISTICS:列出各种缓存设置和内存使用统计数据。
这个特殊说明下字段:
Create Count Success:新建的result cache的数量
Find Count:说明使用result cache的次数
Create Count Failure:说明创建result cache失败的数量
V$RESULT_CACHE_MEMORY:列出所有的内存块和相应的统计信息。
V$RESULT_CACHE_OBJECTS:列出所有的对象(缓存的结果和依赖的对象)和它们的属性。
V$RESULT_CACHE_DEPENDENCY:列出缓存的结果和依赖对象间的依赖详情。
SQL> desc dbms_result_cache
Element Type
----------------- ---------
STATUS_DISA CONSTANT
STATUS_ENAB CONSTANT
STATUS_BYPS CONSTANT
STATUS_SYNC CONSTANT
STATUS_CORR CONSTANT
STATUS FUNCTION
FLUSH FUNCTION
MEMORY_REPORT PROCEDURE
DELETE_DEPENDENCY FUNCTION
INVALIDATE FUNCTION
INVALIDATE_OBJECT FUNCTION
BYPASS PROCEDURE
SQL>
查看server result cache的内存使用报告
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 = 85024K bytes (85024 blocks)
Maximum Result Size = 4251K bytes (4251 blocks)
[Memory]
Total Memory = 87426840 bytes [5.428% of the Shared Pool]
... Fixed Memory = 68992 bytes [0.004% of the Shared Pool]
... Dynamic Memory = 87357848 bytes [5.424% of the Shared Pool]
....... Overhead = 293272 bytes
....... Cache Memory = 85024K bytes (85024 blocks)
........... Unused Memory = 0 blocks
........... Used Memory = 85024 blocks
............... Dependencies = 89 blocks (89 count)
............... Results = 84935 blocks
................... SQL = 59063 blocks (46593 count)
................... Invalid = 25546 blocks (23785 count)
PL/SQL procedure successfully completed
SQL>
DBMS_RESULT_CACHE功能和存储过程
STATUS存储过程
返回结果缓存的当前状态。值包括:
ENABLED:结果缓存是激活的。
DISABLED:结果缓存是不可用的。
BYPASSED:结果缓存暂时不可用。
SYNC: 结果缓存是可用的,但是目前正与其他RAC节点重新同步。
MEMORY_REPORT存储过程
列出结果缓存内存利用的一个概要(默认)或详细的报表。
FLUSH存储过程
推出整个结果缓存的内容。
INVALIDATE存储过程
使结果缓存中一个特定对象的缓存结果无效。
INVALIDATE_OBJECT存储过程
根据缓存ID使一特定结果缓存无效。
query cache result特性所占据的内存是从sga的share pool中分配,如下视图可以看到
SQL> select * from v$sgastat where lower(name) like '%result%';
POOL NAME BYTES
------------ -------------------------- ----------
shared pool Result Cache: State Objs 66536
shared pool Result Cache 87357848
shared pool Result Cache: Memory Mgr 200
shared pool Result Cache: Cache Mgr 208
shared pool Result Cache: Bloom Fltr 2048
SQL>
result cache也有类似enqueue/lock的保护机制,RC enqueue就是拿来保护并发修改的。result cache他依赖是object level的,
既不是row level的,也不是block level的。任何DML/DDL(甚至包括grant)都会使基于这个object的result cache变为invalidate。
所以result cache只有对那些在平时几乎没有任何DML的只读表比较有用,可以减轻io的压力。
在平时读取阶段不是使用的shared pool latch,而是使用的result cache latch,如下所示
SQL> select * from v$latchname where name like 'Result Cache%';
LATCH# NAME HASH
---------- ---------------------------------------------------------------- ----------
405 Result Cache: RC Latch 1054203712
406 Result Cache: SO Latch 986859868
407 Result Cache: MB Latch 995186388
检查result cache配置是否生效
1.select dbms_result_cache.status from dual;
2.dbms_result_cache.MEMORY_REPORT
3.查看sql执行计划
注意:
11g的active dataguard的备库是不能使用result cache的,这是oracle的一个bug,因为涉及到内码的问题,所以oracle一直没有修复,result cache目前可以使用在单节点主库和rac环境。
SQL> select count(*) from t;
COUNT(*)
----------
13456
SQL> set autot on;
SQL> select count(*) from t;
COUNT(*)
----------
13456
----------------------------------------------------------
Plan hash value: 2966233522
-------------------------------------------------------------------
| Id | Operation | Name |Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0| SELECT STATEMENT | | 1 | 50 (2)| 00:00:01 |
| 1| SORT AGGREGATE | | 1 | | |
| 2| TABLE ACCESS FULL| T | 12278 | 50 (2)| 00:00:01 |
-------------------------------------------------------------------
SQL> select *+ result_cache */ count(*)from t;
COUNT(*)
----------
13456
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0| SELECT STATEMENT | | 1 | 50 (2)| 00:00:01 |
| 1| RESULT CACHE | c8ukugu9jf5474pjzn83wj3zph | | | |
| 2| SORT AGGREGATE | | 1 | | |
| 3| TABLE ACCESS FULL| T | 12278 | 50 (2)| 00:00:01 |
---修改为force,则强制使用resultcache
alter system set result_cache_mode=force;
SQL> create table t1 as select * from t;
SQL> select count(*) from t1;
COUNT(*)
----------
13456
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0| SELECT STATEMENT | | 1 | 50 (2)| 00:00:01 |
| 1| RESULT CACHE | 8q8qwtn4uk3vv7sm1ynpzz6t4k | | | |
| 2| SORT AGGREGATE | | 1 | | |
| 3| TABLE ACCESS FULL| T1 | 14242 | 50 (2)| 00:00:01 |
------------------------------------------------------------------------------------------
SQL> select count(*) from t1;
COUNT(*)
----------
13456
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0| SELECT STATEMENT | | 1 | 50 (2)| 00:00:01 |
| 1| RESULT CACHE | 8q8qwtn4uk3vv7sm1ynpzz6t4k | | | |
| 2| SORT AGGREGATE | | 1 | | |
| 3| TABLE ACCESS FULL| T1 | 14242 | 50 (2)| 00:00:01 |
------------------------------------------------------------------------------------------
查询V$RESULT_CACHE_OBJECTS可以得到目前缓存的情况
1*select name,cache_id from V$RESULT_CACHE_OBJECTS
SQL> select name,cache_id fromV$RESULT_CACHE_OBJECTS;
NAME CACHE_ID
------------------------------------------------------------------------------------------------------------------------
WJ.T1 WJ.T1
WJ.T WJ.T
select count(*) from t1 8q8qwtn4uk3vv7sm1ynpzz6t4k
select *+ result_cache */ count(*) fromt c8ukugu9jf5474pjzn83wj3zph
2,使用Table Annotations。 表注释的优先级低于sql语句。通过关键字RESULT_CACHE来实现。有DEFAULT和FORCE两个数值
DEFAULT
If at least one table in a query is set to DEFAULT, then result cachingis not enabled at the table level for this query, unless the RESULT_CACHE_MODEinitialization parameter is set to FORCE or the RESULT_CACHE hint is specified.This is the default value.
FORCE
If all the tables of a query are marked as FORCE, then the query resultis considered for caching. The table annotation FORCE takes precedence over theRESULT_CACHE_MODE parameter value of MANUAL set at the session level.
测试结果如下
SQL> alter table t1 result_cache (MODEforce);
SQL> alter session set result_cache_mode= MANUAL;
--查询T1使用resultcache
SQL> select count(*) from t1;
COUNT(*)
----------
13456
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0| SELECT STATEMENT | | 1 | 50 (2)| 00:00:01 |
| 1| RESULT CACHE | 8q8qwtn4uk3vv7sm1ynpzz6t4k | | | |
| 2| SORT AGGREGATE | | 1 | | |
| 3| TABLE ACCESS FULL| T1 | 14242 | 50 (2)| 00:00:01 |
------------------------------------------------------------------------------------------
--查询表T没有使用resultcache
SQL> select count(*) from t;
COUNT(*)
----------
13456
-------------------------------------------------------------------
| Id | Operation | Name |Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0| SELECT STATEMENT | | 1 | 50 (2)| 00:00:01 |
| 1| SORT AGGREGATE | | 1 | | |
| 2| TABLE ACCESS FULL| T | 12278 | 50 (2)| 00:00:01 |
扫描二维码关注我的微学堂
搜索刘老师微信号:Rman-2014,备注“Oracle学习与咨询”,即可添加好友;或者扫描下面二维码,关注我的“微学堂”公众号,了解最新OCP认证动态、题库及答案解析、培训机构及讲师介绍、课堂授课内容等。每天还有一篇技术文章发布哦!