结果集缓存(Result Cache)是Oracle Database 11g新引入的功能,除了可以在服务器端缓存结果集(Server Result Cache)之外,还可以在客户端缓存结果集(Client Result Cache)。下面着重介绍一下服务器端结果集缓存。
服务器端的Result Cache Memory由两部分组成。
l SQL Query Result Cache:存储SQL查询的结果集。
l PL/SQL Function Result Cache:用于存储PL/SQL函数的结果集。
Oracle通过一个新引入初始化参数result_cache_max_size来控制该Cache的大小。如果result_cache_max_size=0则表示禁用该特性。参数result_cache_max_result则控制单个缓存结果可以占总的Server Result Cache大小的百分比。
SQL> select * from v$version where rownum <2; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production 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 1280K result_cache_mode string MANUAL result_cache_remote_expiration integer 0
上面显示的参数中result_cache_mode用于控制Server result cache的模式,该参数有3个可选设置。
l 设置auto:则优化器会自动判断是否将查询结果缓存。
l 设置manual:则需要通过查询提示result_cache来告诉优化器是否缓存结果。
l 设置force :则尽可能地缓存查询结果(通过提示no_result_cache可以拒绝缓存)。
下面通过测试来看一下这一新特性的使用及优势所在,首先创建一张测试表:
SQL> connect eygle/eygle Connected. SQL> create table eygle as select * from dba_objects; Table created.
在以前版本中,第一次执行该SQL可以看到consistent gets和physical reads大致相同:
SQL> set autotrace on SQL> select count(*) from eygle; COUNT(*) ---------- 15993 Statistics ---------------------------------------------------------- 28 recursive calls 0 db block gets 282 consistent gets 217 physical reads
再次执行同样查询时,由于数据Cache在内存中,physical reads会减少到0,但是consistent gets很难降低:
SQL> select count(*) from eygle; COUNT(*) ---------- 15993 Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 221 consistent gets 0 physical reads
现在再来看看在Server Result Cache下Oracle的行为,首先在result_cache_mode参数设置为MANUAL时:
SQL> show parameter result_cache_mode NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ result_cache_mode string MANUAL
需要在SQL语句中手工指定Cache,这需要通过加入一个hints来实现,这个hints是result_cache:
SQL> select /*+ result_cache */ count(*) from eygle; COUNT(*) ---------- 15993 Execution Plan ---------------------------------------------------------- Plan hash value: 3602634261 ----------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ----------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 64 (0)| 00:00:01 | | 1 | RESULT CACHE | 76rwwyazv6t6c39f1d8rrqh8rb | | | | | 2 | SORT AGGREGATE | | 1 | | | | 3 | TABLE ACCESS FULL| EYGLE | 14489 | 64 (0)| 00:00:01 | ----------------------------------------------------------------------------------------- Result Cache Information (identified by operation id): ------------------------------------------------------ 1 - column-count=1; dependencies=(EYGLE.EYGLE); attributes=(single-row); name="select /*+ result_cache */ count(*) from eygle" Statistics ---------------------------------------------------------- 4 recursive calls 0 db block gets 280 consistent gets 0 physical reads
注意到这个执行计划已经和以往的不同,RESULT CACHE以76rwwyazv6t6c39f1d8rrqh8rb名称创建。那么在接下来的查询中,这个Result Cache就可以被利用:
SQL> select /*+ result_cache */ count(*) from eygle; COUNT(*) ---------- 15993 Execution Plan ---------------------------------------------------------- Plan hash value: 3602634261 ----------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ----------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 64 (0) | 00:00:01 | | 1 | RESULT CACHE | 76rwwyazv6t6c39f1d8rrqh8rb | | | | | 2 | SORT AGGREGATE | | 1 | | | | 3 | TABLE ACCESS FULL| EYGLE | 14489| 64 (0)| 00:00:01 | ----------------------------------------------------------------------------------------- Result Cache Information (identified by operation id): ------------------------------------------------------ 1 - column-count=1; dependencies=(EYGLE.EYGLE); attributes=(single-row); name="select /*+ result_cache */ count(*) from eygle" Note ----- - dynamic sampling used for this statement Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 0 consistent gets 0 physical reads 0 redo size
在这个利用到Result Cache的查询中,consistent gets减少到0,直接访问结果集,不再需要执行SQL查询。这就是Result Cache的强大之处。
在以上测试中,当result_cache_mode设置为MANUAL时,只有使用hints的情况下,Oracle才会利用缓存结果集;而如果将result_cache_mode设置为AUTO,Oracle如果发现缓冲结果集已经存在,那么就会自动使用。但是如果缓冲结果集不存在,Oracle并不会自动进行缓冲,只有使用HINT的情况下,Oracle才会将执行的结果集缓存。
可以通过查询v$result_cache_memory视图来看Cache的使用情况:
SQL> select * from V$RESULT_CACHE_MEMORY 2 where FREE='NO'; ID CHUNK OFFSET FRE OBJECT_ID POSITION --------- ---------- ---------- --- ---------- ---------- 0 0 0 NO 0 0 1 0 1 NO 1 0
通过V$RESULT_CACHE_STATISTICS可以查询Result Cache的统计信息:
SQL> select * from V$RESULT_CACHE_STATISTICS; ID NAME VALUE ---------- ------------------------------ ---------- 1 Block Size (Bytes) 1024 2 Block Count Maximum 992 3 Block Count Current 32 4 Result Size Maximum (Blocks) 49 V$RESULT_CACHE_OBJECTS记录了Cache的对象: SQL> SELECT ID,TYPE,NAME,BLOCK_COUNT,ROW_COUNT FROM V$RESULT_CACHE_OBJECTS; ID TYPE NAME BLOCK_COUNT ROW_COUNT ---------- ---------- ------------------------------ ----------- ---------- 0 Dependency EYGLE.EYGLE 1 0 1 Result select /*+ result_cache */ cou 1 1 nt(*) from eygle
一个新的系统包被引入,DBMS_RESULT_CACHE可以用于执行关于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 = 992K bytes (992 blocks) Maximum Result Size = 49K bytes (49 blocks) [Memory] Total Memory = 100836 bytes [0.059% of the Shared Pool] ... Fixed Memory = 5132 bytes [0.003% of the Shared Pool] ... Dynamic Memory = 95704 bytes [0.056% of the Shared Pool] ....... Overhead = 62936 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.