在11g中,Oracle提供了结果集缓存特性。该缓存是在共享内存中存储全部的结果集,如果一个查询SQL被执行,且它对应的结果集在缓存中,那么,该SQL的几乎全部开销都可以避免。这些开销包括,解析时间、逻辑读、物理读和任意的通常可能会遭遇的争用。但是,在实际的情况中,结果集缓存仅在少数的情况下是有效的,原因有如下几点:
(1)有数据重叠的多个SQL会在缓存中保存冗余的数据。
(2)对依赖对象的任何改变(包括对查询中引用的任意表)都会使整个缓存的结果集变为无效,结果集缓存最适合那些只读或接近只读的表。
(3)大的结果集要么是因为结果集缓存太少不能放入,要么会强迫缓存中所有已存在的条件换出。为了防止这种情况发生,我们必须限制结果集缓存仅用于较小的结果集。
(4)在缓存中快速并发的结果集的创建可能会导致结果集闩锁的争用。因此,结果集缓存的内容必须变得相对慢一些。
result_cache_mode :该参数用来控制结果集缓存的操作模式。OFF表示禁用,MANUAL表示只有使用了result_cahce提示的查询或对带有result_cache(mode force)属性的表访问的查询才会被缓存。FORCE表示所有合适的查询都会被缓存。
result_cache_max_size:控制结果集缓存的大小,默认是共享池的1%。
result_cache_max_result:单个结果集能够消耗的缓存的最大百分比。比这个值大的,将不能被缓存。
下面,我们来进行一个配置:
SQL> alter session set result_cache_mode = manual
--------------------------------------------------------------------------------
---------------------------
| Id | Operation | Name | Rows | Byte
s | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
---------------------------
| 0 | SELECT STATEMENT | | 100 | 860
0 | 4 (0)| 00:00:01 |
| 1 |
RESULT CACHE | c588m2d8c1u4f4qb361bw3h58y |
|
| | |
| 2 | TABLE ACCESS BY INDEX ROWID| T | 100 | 860
0 | 4 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_PK | 100 |
| 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------
---------------------------
--------------------------------------------------------------------------------
---------------------------
| Id | Operation | Name | Rows | Byte
s | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
---------------------------
| 0 | SELECT STATEMENT | | 100 | 860
0 | 4 (0)| 00:00:01 |
| 1 | RESULT CACHE | c588m2d8c1u4f4qb361bw3h58y | |
| | |
| 2 | TABLE ACCESS BY INDEX ROWID| T | 100 | 860
0 | 4 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_PK | 100 |
| 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------
---------------------------
13 join v$sql s on (s.sql_id = p.sql_id and s.child_number = p.child_number)
14 where operation = upper('result cache')
15 order by 7 desc
16 /
众所周知,内存的访问速度远远高于磁盘,把经常使用的数据存放于内存中来提高检索速度已不是什么新鲜事了。Cache 是内存中的一片区域,也叫缓存,如今关系型数据库正是利用这一种重要机制,使得访问数据库的性能突飞猛进。
Result Cache简述
数据库在构建一个SQL查询结果时,不仅需要在访问数据上消耗时间,数据的排序、聚合以及连接操作也会消耗一部分时间。对此Oracle 在11g R1版本中引入了Result Cache(结果集缓存),目的就是将查询结果直接放入内存中,节省构建结果集所花费的时间和资源。引擎可以直接返回结果,而不必在缓存中读取数据.
我们可以把SQL执行概括为三个阶段:
1.从存储获取数据到内存(对于尚未在缓存中的数据)
2.对缓存数据集进行筛选
3.返回结果集给客户端
Client Result Cache,通过应用程序层配置,缓存结果集位于客户端内存中。并可以在所有Session间共享,当查询被反复执行时,查询结果可以直接从客户端的缓存中获得,从而极大地提高了应用效率。
Result Cache 特性可以通过一些动态参数进行控制,比如用以定义结果集的内存池的大小、触发的方式等。
默认情况下,如果基础表发生改变,Oracle会将Result Cache中的结果集设置为无效,使得客户端不会从结果缓存中获取过时的数据。当查询运行时,失效的Result Cache结果集将重新被缓存,然后在提交DML发生数据修改时再次被设置为无效。
Result Cache使用监控(相关查看包及视图)
Result Cache的读取和修改与其他Oracle部分内存池的读取修改情况类似,也是通过Latch锁进行保护,读取缓存池时需要持有共享锁,修改时(用于添加新的结果集或使现有结果集无效)需要持有排他锁,以避免其他会话同时访问。
因此频繁的更新Result Cache中对应的表格会引起Latch锁的争用(特别是RC Latch)
某客户从AIX平台迁移到x86稳定运行半个月后,高峰期时常出现卡顿,提取故障点的awr及ash报告。从上述等待事件可以看出数据库大部分时间都花在enq: TX – row lock contention和latch free上。
第一反应可能觉得是enq: TX – row lock contention引起的故障,但随后进一步沟通发现,从迁移之后程序代码并无变化。既然业务逻辑没有改变TX锁引起此次故障可能性不大,初步判定是由于latch free 使得TX锁加剧。继续查看latch free 相关的信息。
查看result相关参数其中result_cache_mode为force,解决办法可以直接把result_cache_mode改成manual或直接禁用result cache 设置result_cache_max_size为0。
Result Cache是Oracle又一个进步,能大幅提升性能,但也像其他特性一样,不是所有的会话都适用。
1、概述:Oracle 从11g开始引入了结果集缓存(result cache)的新特性,用于存储经常使用的SQL语句和函数的查询结果,将来语句再执行的时候,oracle直接的访问内存得到结果
2、优点:重用相同的结果集,减少逻辑IO,提高系统性能
3、分类:oracle数据库引擎提供了三种结果集缓存,包括:服务器查询结果集缓存、pl/sql函数结果集缓存和客户端结果集缓存
4、应用场合:访问多行返回少数行的语句,非常适合只读、读>>写、典型OLTP等系统的功能;ORACLE建议应用仅仅对read only的表中使用result cache缓存功能
5、影响因素:在SGA中缓存sql语句的执行结果,相同sql再次执行时,直接从SGA直接读结果就可以了,不需要在去数据库中扫描索引,或是回表,计算之类的,
若sql中对应的对象(比如表)做了update,insert,delete或是ddl操作,相关所有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
6、使用限制:
(1)查询使用非确定性的函数,序列和临时表的结果集不会被缓存
(2)查询违反了读一致性时结果集将不会被缓存
(3)引用数据字典视图的查询的结果集不会被缓存
(4)查询结果集大于可用缓存结果集可用空间的不被缓存;采用LRU算法来管理result cache。
二、服务器端结果集缓存
1、 相关参数说明
影响result cache开启使用的两个参数:result_cache_mode和result_cache_max_size
RESULT_CACHE_MODE
参数有三个值:AUTO、MANUAL 和FORCE
(1) 设置为AUTO 时,优化程序将根据重复的执行操作确定将哪些结果存储在高速缓存中。
(2) 设置为MANUAL(默认值)时,必须使用RESULT_CACHE (v$sql_hint视图查看hint信息) 提示指定在高速缓存中存储特定结果。
(3) 设置为FORCE 时,所有结果都将存储在高速缓存中。
注:对于AUTO 和FORCE 设置,如果语句中包含[NO_]RESULT_CACHE 提示,则该提示优先于参数设置。
RESULT_CACHE_MAX_SIZE
参数设置分配给结果高速缓存的内存,如果将其值设为0,则会禁用结果高速缓存
默认值取决于其它三个内存参数设置(memory_target的0.25% 或sga_target 的0.5% 或shared_pool_size 的1%),其值为32K的整数倍;
官档提示:Oracle Database will not allocate more than 75% of the shared pool to the server result cache
实验结果:最大值不会大于三个内存参数设置的80%(按shared_pool_size、sga_target、memory_target依次优先检查设置的值)。
即:当三个都设置了时,以shared_pool_size为准;shared_pool_size没设置时,以sga_target为准;只有memory_target设置时,以memory_target为准。
注意:无论默认取值还是最大取值,约定为大于等于指定值的最小32K倍数值;如当shared_pool_size=100K时,则80%为80K,80K不是32K整数倍,大于80K的32K倍数值最小值为96K;
重置shared_pool_size或shared_pool_size为0时,并不认为没有设置,此时RESULT_CACHE_MAX_SIZE始终为0(由于最大值是0的80%的缘故);当修改过这三个值0时,要恢复不设置
状态,可以生成pfile,从pfile中删除对应参数记录
计算公式参数值换算成KB单位:
--默认值
shared_pool_size(GB):SELECT CEIL(shared_pool_size * 0.01 / 32) * 32||'K' AS "RESULT_CACHE_MAX_SIZE" FROM dual;
sga_target(GB):SELECT CEIL(sga_target * 0.01 * 0.5 / 32) * 32||'K' AS "RESULT_CACHE_MAX_SIZE" FROM dual;
memory_target(GB):SELECT CEIL(memory_target * 0.01 * 0.25 / 32) * 32||'K' AS "RESULT_CACHE_MAX_SIZE" FROM dual;
--最大值
SELECT 'result_cache_max_size' as "NAME", CEIL(para_size * 0.8 / 32) * 32 / 1024 ||'K' AS "DISPLAY_VALUE" FROM dual;
新装数据库根据选择ASSM还是AMM觉定(memory_target和shared_pool_size有一值为0,一值为非0值)。
--选择ASMM
col name for a30
col display_value for a30
select name,display_value from v$parameter where name in ('memory_target','shared_pool_size','sga_target', 'result_cache_max_size');
NAME DISPLAY_VALUE
------------------------------ ------------------------------
shared_pool_size 0
sga_target 3G
memory_target 0
result_cache_max_size 15744K
col name for a30
col display_value for a30
SELECT 'result_cache_max_size' as "NAME", CEIL(3 * 1024 * 1024 * 0.01 * 0.5 / 32) * 32||'K' AS "DISPLAY_VALUE" FROM dual;
NAME DISPLAY_VALUE
------------------------------ ------------------------------
result_cache_max_size 15744K
--选择AMM
col name for a30
col display_value for a30
select name,display_value from v$parameter where name in ('memory_target','shared_pool_size','sga_target', 'result_cache_max_size');
NAME DISPLAY_VALUE
------------------------------ ------------------------------
shared_pool_size 0
sga_target 0
memory_target 4G
result_cache_max_size 10496K
col name for a30
col display_value for a30
SELECT 'result_cache_max_size' as "NAME", CEIL(4 * 1024 * 1024 * 0.01 * 0.25 / 32) * 32||'K' AS "DISPLAY_VALUE" FROM dual;
NAME DISPLAY_VALUE
------------------------------ ------------------------------
result_cache_max_size 10496K
--选择MSMM
col name for a30
col display_value for a30
select name,display_value from v$parameter where name in ('memory_target','shared_pool_size','sga_target', 'result_cache_max_size');
NAME DISPLAY_VALUE
------------------------------ ------------------------------
shared_pool_size 480M
sga_target 0
memory_target 0
result_cache_max_size 4928K
col name for a30
col display_value for a30
SELECT 'result_cache_max_size' as "NAME", CEIL(480 * 1024 * 0.01 / 32) * 32||'K' AS "DISPLAY_VALUE" FROM dual;
NAME DISPLAY_VALUE
------------------------------ ------------------------------
result_cache_max_size 4928K
SQL> ALTER SYSTEM SET result_cache_max_size=1g;
System altered.
SQL> select name,display_value from v$parameter where name in ('memory_target','shared_pool_size','sga_target', 'result_cache_max_size');
NAME DISPLAY_VALUE
------------------------------ ------------------------------
shared_pool_size 480M
sga_target 0
memory_target 0
result_cache_max_size 384M
SQL> select 384/480 from dual;
384/480
----------
小结:由上可知,RESULT_CACHE_MAX_SIZE三种默认取值恰好对应的是数据库内存的三种管理模式(AMM、ASMM和MSMM);手动设置时,最大值为shared_pool_size的80%
RESULT_CACHE_MAX_RESULT
限制单个result所能占据query cache的最大百分比大小;默认是5%
RESULT_CACHE_REMOTE_EXPIRATION
设置远程数据库结果集缓存过期的时间,以分钟为单位,默认值为0不缓存远程数据库结果集
2、相关视图说明
V$RESULT_CACHE_STATISTICS:列出各种缓存设置和内存使用统计数据。
V$RESULT_CACHE_MEMORY:列出所有的内存块和相应的统计信息。
V$RESULT_CACHE_OBJECTS:列出所有的对象(缓存的结果和依赖的对象)和它们的属性。
V$RESULT_CACHE_DEPENDENCY:列出缓存的结果和依赖对象间的依赖详情。
3、相关的包:DBMS_RESULT_CACHE
3.1 STATUS存储过程
--DISABLED:表示没有开启
--ENABLE :表示已经开启了,并且可以使用结果集缓存
--BYPASS :表是已经开启了,但不可以使用结果集缓存(跳过了),此时可以通过执行 exec dbms_result_cache.bypass(FALSE);
-----------如果仍然是bypass则可能是参数result_cache_max_size 的值为0的原因
--SYNC :结果缓存是可用的,但是目前正与其他RAC节点重新同步。
3.2 MEMORY_REPORT存储过程 :列出结果缓存内存利用的一个概要(默认)或详细的报表。
3.3 FLUSH存储过程 :清空整个结果缓存的内容。
3.4 INVALIDATE存储过程 :使结果缓存中一个特定对象的缓存结果无效。
3.5 INVALIDATE_OBJECT存储过程:根据缓存ID使一特定结果缓存无效。
注意: 11g的active dataguard的备库是不能使用result cache的,这是oracle的一个bug,因为涉及到内码的问题,所以oracle一直没有修复,
result cache目前可以使用在单节点主库和rac环境。
开启result cache
1、设置RESULT_CACHE_MODE为FORCE
2、根据内存管理方式调整相关参数,设置RESULT_CACHE_MAX_SIZE大小
3、检查result cache是否开启:select dbms_result_cache.status from dual;
关于设置result cache遇到的问题:
场景: 安装库时选择的是ASMM模式,后来ASMM调整成了AMM,设置sga_target=0;导致设置result_cache_max_size时始终为0设置不了其他值
原因: ASMM时,result_cache_max_size以sga_target参数为参考值,当设置sga_target=0时,由于sga_target还存在于spfile中;使得result_cache_max_size仍以sga_target参数为参考值,
由最大值限制,result_cache_max_size时始终为0
解决: 执行alter system reset sga_target;重启库设置result_cache_max_size值;这样使得sga_target从spfile中删除;从而result_cache_max_size以memory_target参数为参考值
扩展:result_cache_max_size从spfile中shared_pool_size、sga_target和memory_target依次查找选择参考值
查找参数是否在spfile中(isspecified为TRUE表示指定在spfile中):
SELECT NAME, VALUE, display_value, isspecified
FROM v$spparameter
WHERE NAME IN ('memory_max_target',
'memory_target',
'sga_max_size',
'sga_target',
'shared_pool_size',
'result_cache_max_size')
ORDER BY NAME;
众所周知,访问内存比访问硬盘快得多,除非硬盘体系发生革命性的改变。可以说缓存在Oracle里面无处不在,结果集缓存(Result Cache)是Oracle Database 11g新引入的功能,引入它的目的在于可以重用相同的结果集,减少逻辑IO,提高系统性能。结果集缓存又分为:服务端缓存和客户端缓存。
一、服务端缓存
1.服务器端的Result Cache Memorey由两部分组成。
(1)SQL Query Result Cache:存储SQL查询的结果集。
(2)PL/SQL Function Result Cache:用于存储PL/SQL函数的结果集。
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 10M
result_cache_mode string MANUAL
result_cache_remote_expiration integer 0
如果设置的值为MANUAL,用户必须用reslut_cache 提示才可以缓存结果集。
如果设置为FORCE,ORACLE会缓冲所有的结果,除非用户用了no_result_cache提示。
如果设置为AUTO,优化器会自动判断是否将查询结果缓存。
2.3 RESULT_CACHE_MAX_RESULT
该参数是控制单个result所能占据RESULT_CACHE_MAX_SIZE的大小比例,注意是一个百分比。
该参数默认是是5%,取值范围当然是1% ~ 100% 了。
2.4 result_cache_remote_expiration
该参数的作用是根据远程数据库对象设置缓存过期的时间,默认值为0.
也就是说,默认情况下,远程数据库对象不会被进行cache的。
V$RESULT_CACHE_STATISTICS:列出各种缓存设置和内存使用统计数据。
V$RESULT_CACHE_MEMORY:列出所有的内存块和相应的统计信息。
V$RESULT_CACHE_OBJECTS:列出所有的对象(缓存的结果和依赖的对象)和它们的属性。
V$RESULT_CACHE_DEPENDENCY:列出缓存的结果和依赖对象间的依赖详情。
4.Oracle还提供了一个包来管理server result cache:dbms_result_cache
4.1查看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 = 10M bytes (10K blocks)
Maximum Result Size = 512K bytes (512 blocks)
[Memory]
Total Memory = 110476 bytes [0.018% of the Shared Pool]
... Fixed Memory = 12080 bytes [0.002% of the Shared Pool]
... Dynamic Memory = 98396 bytes [0.016% of the Shared Pool]
....... Overhead = 65628 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.
Execution Plan
----------------------------------------------------------
Plan hash value: 1435881708
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 74795 | 1241K| 291 (2)| 00:00:04 |
| 1 | RESULT CACHE | 6fpdv8pg615sh5j0pw1t1jn3wq | | | | |
| 2 | HASH GROUP BY | | 74795 | 1241K| 291 (2)| 00:00:04 |
| 3 | TABLE ACCESS FULL| TEST | 74795 | 1241K| 289 (1)| 00:00:04 |
--------------------------------------------------------------------------------------------------
Result Cache Information (identified by operation id):
------------------------------------------------------
1 - column-count=2; dependencies=(TEST.TEST); parameters=(nls); name="select /*+ result_cache */
owner,count(*) from test group by owner"
----------------------------------------------------------
48 recursive calls
0 db block gets
1109 consistent gets
1031 physical reads
0 redo size
1035 bytes sent via SQL*Net to client
430 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
28 rows processed
SQL> select /*+ result_cache */ owner,count(*) from test group by owner;
28 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1435881708
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 74795 | 1241K| 291 (2)| 00:00:04 |
| 1 | RESULT CACHE | 6fpdv8pg615sh5j0pw1t1jn3wq | | | | |
| 2 | HASH GROUP BY | | 74795 | 1241K| 291 (2)| 00:00:04 |
| 3 | TABLE ACCESS FULL| TEST | 74795 | 1241K| 289 (1)| 00:00:04 |
--------------------------------------------------------------------------------------------------
Result Cache Information (identified by operation id):
------------------------------------------------------
1 - column-count=2; dependencies=(TEST.TEST); parameters=(nls); name="select /*+ result_cache */
owner,count(*) from test group by owner"
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
1035 bytes sent via SQL*Net to client
430 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
28 rows processed
从执行计划中可以看到标黄色的地方,就是对应 v$result_cache_objects的cache_id的。在第二次查询的执行计划中,发现逻辑读已经变成0 了,说明result cache起作用了。
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 = 10M bytes (10K blocks)
Maximum Result Size = 512K bytes (512 blocks)
[Memory]
Total Memory = 110476 bytes [0.018% of the Shared Pool]
... Fixed Memory = 12080 bytes [0.002% of the Shared Pool]
... Dynamic Memory = 98396 bytes [0.016% of the Shared Pool]
....... Overhead = 65628 bytes
....... Cache Memory = 32K bytes (32 blocks)
........... Unused Memory = 0 blocks
........... Used Memory = 32 blocks
............... Dependencies = 3 blocks (3 count)
............... Results = 29 blocks
................... SQL = 1 blocks (1 count)
................... Invalid = 28 blocks (28 count)
PL/SQL procedure successfully completed.
SQL> select * from v$result_cache_statistics;
ID NAME VALUE
---------- ------------------------------ ------------------------------
1 Block Size (Bytes) 1024
2 Block Count Maximum 10240
3 Block Count Current 32
4 Result Size Maximum (Blocks) 512
5 Create Count Success 30166
6 Create Count Failure 0
7 Find Count 3
8 Invalidation Count 2
9 Delete Count Invalid 30137
10 Delete Count Valid 0
11 Hash Chain Length 1
11 rows selected.
再来看看相应的report和统计信息。
SQL> select * from v$result_cache_statistics;
ID NAME VALUE
---------- ------------------------------ ------------------------------
1 Block Size (Bytes) 1024
2 Block Count Maximum 10240
3 Block Count Current 32
4 Result Size Maximum (Blocks) 512
5 Create Count Success 30166
6 Create Count Failure 0
7 Find Count 3
8 Invalidation Count 2
9 Delete Count Invalid 30137
10 Delete Count Valid 0
11 Hash Chain Length 1
11 rows selected.
SQL> select /*+ result_cache */ owner,count(*) from test group by owner;
OWNER COUNT(*)
------------------------------------------------------------ ----------
LZQ 2
OWBSYS_AUDIT 12
MDSYS 1509
PUBLIC 27696
OUTLN 9
TEST 9
CTXSYS 366
OLAPSYS 719
FLOWS_FILES 12
OWBSYS 2
SYSTEM 529
OWNER COUNT(*)
------------------------------------------------------------ ----------
ORACLE_OCM 8
EXFSYS 310
APEX_030200 2406
SCOTT 6
ISC 558
DBSNMP 65
ORDSYS 2532
ORDPLUGINS 10
SYSMAN 3491
SURE 1
APPQOSSYS 3
OWNER COUNT(*)
------------------------------------------------------------ ----------
XDB 842
ORDDATA 248
SS 1
SYS 30792
WMSYS 316
SI_INFORMTN_SCHEMA 8
28 rows selected.
SQL> select * from v$result_cache_statistics;
ID NAME VALUE
---------- ------------------------------ ------------------------------
1 Block Size (Bytes) 1024
2 Block Count Maximum 10240
3 Block Count Current 32
4 Result Size Maximum (Blocks) 512
5 Create Count Success 30226
6 Create Count Failure 0
7 Find Count 4
8 Invalidation Count 2
9 Delete Count Invalid 30197
10 Delete Count Valid 0
11 Hash Chain Length 1
11 rows selected.
注意到Find Count = 1,说明上次缓存的结果被后面的查询应用了一次。如果继续执行该查询,可以发现该统计信息会相应增加。
我们可以根据cache_id去 v$result_cache_objects查询相关的信息
SQL> select name,cache_id from v$result_cache_objects t where t.CACHE_ID='6fpdv8pg615sh5j0pw1t1jn3wq'
------------------------------
CACHE_ID
---------------------------------------------------------------------------------------------------
select /*+ result_cache */ own
er,count(*) from test group by
owner
6fpdv8pg615sh5j0pw1t1jn3wq
6.深入认识result cache
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 5492
shared pool Result Cache 98396
shared pool Result Cache: Memory Mgr 124
shared pool Result Cache: Bloom Fltr 2048
shared pool Result Cache: Cache Mgr 4416
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,如下所示
LATCH# NAME HASH
---------- ------------------------- ----------
391 Result Cache: RC Latch 1054203712
392 Result Cache: SO Latch 986859868
393 Result Cache: MB Latch 995186388
检查result cache配置是否生效
1.select dbms_result_cache.status from dual;
2.dbms_result_cache.MEMORY_REPORT
3.查看sql执行计划中是否还有关键字:result cache
11g的active dataguard的备库是不能使用result cache的,result cache目前可以使用在单节点主库和rac环境。
假设有这样一个情形:客户端需要通过慢速网络链接调用同一数据。尽管数据库可以立即将结果从缓存发送到客户端,但结果必须通过线路传送到客户端,这就增加了整体执行时间。现在有一些专门的中间件框架(如 Oracle Coherence),用于在 Java、PHP 和 Ruby 中缓存数据,如果有一个在客户端级别缓存数据的通用方法,又将如何呢?
为此,Oracle 数据库 11g 提供了“客户端查询结果缓存”。所有使用 OCI8 驱动程序的数据库客户端堆栈(C、C++、JDBC-OCI 等)都可以使用这一新特性,使客户端能够在本地缓存 SQL 查询的结果,而不是在服务器上。总言之,客户端查询结果缓存可以提供以下好处:
(1)使应用程序开发人员不用构建由所有会话共享的一致的每一流程的 SQL 结果缓存
(2)通过利用更便宜的客户端内存并在本地缓存每个应用程序的工作集,将服务器端查询缓存扩展到客户端内存,
(3)从而消除到服务器的往返过程,确保更好的性能
(4)通过节约服务器资源,改善服务器可伸缩性
(5)提供透明的缓存管理:内存管理、结果集的并发访问等
(6)透明地维护缓存与服务器端更改的一致性
(7)在 RAC 环境中提供一致性
要使用这一特性,所要做的就是设置一个初始化参数:CLIENT_RESULT_CACHE_SIZE = 1G
该参数定义客户端缓存为 1GB,这是所有客户端的总缓存大小。(这是一个静态参数,因此必须重启数据库来设置)可以在每个客户端中设置缓存,在客户端位置的 SQLNET.ORA 文件中指定其他参数:
让我们看一看它的使用方式。这是简单的 Java 代码,它使用 OCI8 驱动程序连接到数据库,然后执行 SQL 语句:select /*+ result_cache */ * from customers。提示致使语句缓存该结果(其他参数已经设置好)。
public class CacheTest {
private String jdbcURL = "jdbc:oracle:oci8:@orcl";
private Connection conn = null;
public CacheTest( ) throws ClassNotFoundException {
Class.forName("oracle.jdbc.driver.OracleDriver");
public static void main(String[] args) throws ClassNotFoundException, SQLException {
CacheTest check = new CacheTest();
check.dbconnect();
check.doSomething();
public void dbconnect() throws SQLException {
System.out.println("Connecting with URL="+jdbcURL+" as arup/arup");
try {
conn = DriverManager.getConnection( jdbcURL, "arup" , "arup");
System.out.println("Connected to Database");
} catch (SQLException sqlEx) {
System.out.println(" Error connecting to database : " + sqlEx.toString());
public void doSomething() throws SQLException {
Statement stmt = null;
ResultSet rset = null;
try {
stmt = conn.createStatement();
System.out.println("Created Statement object");
rset = stmt.executeQuery("select /*+ result_cache */ * from customers");
System.out.println("Retrieved ResultSet object");
if(rset.next())
System.out.println("Result:"+rset.getString(1));
} catch (SQLException sqlEx) {
}finally {
try {
System.out.println("Closing Statment & ResultSet Objects");
if (rset != null) rset.close();
if (stmt != null) stmt.close();
if (conn != null) {
System.out.println("Disconnecting...");
conn.close();
System.out.println("Disconnected from Database");
} catch (Exception e) {}
PS: OCI8类似于thin,只是它需要在相关的服务器上装上oracle client才能使用。
oracle 11g 函数结果缓存
oracle数据库用一个单独的缓存区为每一个函数同时保存输入和返回值。这个缓存区被连接到这个数据库实例的全部会话共享,而不是为每一个会话复制
每单函数被调用时,数据库就会检查是否已经缓存了相同的输入值。如果是,函数就不用执行了。把缓存中的值简单返回就是了。
每当发现要修改的是缓存所依赖的表,数据库就会自动把缓存失效。
比如我们建立如下的函数
CREATE OR REPLACE FUNCTION f_object (p_id IN number) RETURN VARCHAR2 RESULT_CACHE AS
v_object varchar2(200);
BEGIN
select object_name into v_object from t_object where object_id=p_id;
return v_object;
END ;
--执行函数
SQL> select f_object(10011) from dual;
F_OBJECT(10011)
--------------------------------------------------------------------------------
KU$_IND_SUBNAME_VIEW
Execution Plan
----------------------------------------------------------
Plan hash value: 1388734953
-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------
Statistics
----------------------------------------------------------
20 recursive calls
0 db block gets
1053 consistent gets
0 physical reads
0 redo size
447 bytes sent via SQL*Net to client
419 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select f_object(10011) from dual;
F_OBJECT(10011)
--------------------------------------------------------------------------------
KU$_IND_SUBNAME_VIEW
Execution Plan
----------------------------------------------------------
Plan hash value: 1388734953
-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
447 bytes sent via SQL*Net to client
419 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> insert into t_object select * from t_object where rownum<2;
1 row created.
Execution Plan
----------------------------------------------------------
Plan hash value: 3381357465
--------------------------------------------------------------------------------
-----
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
--------------------------------------------------------------------------------
-----
| 0 | INSERT STATEMENT | | 1 | 207 | 297 (1)| 00:00
:04 |
| 1 | LOAD TABLE CONVENTIONAL | T_OBJECT | | | |
|* 2 | COUNT STOPKEY | | | | |
| 3 | TABLE ACCESS FULL | T_OBJECT | 84104 | 16M| 297 (1)| 00:00
:04 |
--------------------------------------------------------------------------------
-----
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(ROWNUM<2)
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
9 recursive calls
29 db block gets
166 consistent gets
298 physical reads
2052 redo size
678 bytes sent via SQL*Net to client
630 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> commit;
Commit complete.
SQL> select f_object(10011) from dual;
F_OBJECT(10011)
--------------------------------------------------------------------------------
KU$_IND_SUBNAME_VIEW
Execution Plan
----------------------------------------------------------
Plan hash value: 1388734953
-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------
Statistics
----------------------------------------------------------
2 recursive calls
0 db block gets
1047 consistent gets --插入一行数据后,缓存的结构就失效了
726 physical reads
0 redo size
447 bytes sent via SQL*Net to client
419 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
这个功能对静态表非常有用
...............................................................................................................................
● 本文整理自网络
● 本文在itpub(
http://blog.itpub.net/26736162
)、博客园(
http://www.cnblogs.com/lhrbest
)和个人微信公众号(
xiaomaimiaolhr
)上有同步更新
● 本文itpub地址:
http://blog.itpub.net/26736162/abstract/1/
● 本文博客园地址:
http://www.cnblogs.com/lhrbest
● 本文pdf版及小麦苗云盘地址:
http://blog.itpub.net/26736162/viewspace-1624453/
● 数据库笔试面试题库及解答:
http://blog.itpub.net/26736162/viewspace-2134706/
● QQ群:
230161599
微信群:私聊
● 联系我请加QQ好友(646634621),注明添加缘由
● 于 2017-06-02 09:00 ~ 2017-06-30 22:00 在魔都完成
● 文章内容来源于小麦苗的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解
...............................................................................................................................
拿起手机使用
微信客户端
扫描下边的
左边
图片来关注小麦苗的微信公众号:
xiaomaimiaolhr,扫描
右边
的二维码加入小麦苗的QQ群,
学习最实用的数据库技术。
【QQ:646634621】【微信:db_bao】【微信公众号:DB宝】【QQ群:230161599】【Oracle OCP、OCM、高可用(RAC+DG+OGG)、MySQL OCP、PGCA+PGCE+PGCM等都可以找麦老师了】【个人网站:xmmup.com】
注册时间:
2012-09-23
10632940
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员