oracle 11g 新特性之结果缓存

结果缓存,缓存到那里呢?共享池!  也就是说把查询出来的结果集共享到共享池。这样不用解析,不用执行,直接从共享池读取这个结果集就可以,称之为结果缓存。

首先介绍第一种结果缓存:服务器结果缓存

比如一个select查询取出50行记录,就是把这些记录都放在共享池,这个和缓存在buffer cache中是不一样的,大家自己理解一下。buffer cache是获取包含磁盘上的数据块,只要扫描到该块,而且在buffer cache中,那就可以叫做一次逻辑读,而结果缓存是下次执行SQL时,是软解析,直接从共享池取数据记录。

另外一种结果缓存,函数结果缓存,也就是说,把函数计算后的结果缓存到共享池,下次再用此函数,那么就不用计算,直接从共享池取出该值。

最后一种结果缓存,客户端结果缓存。比如服务器在上海,显示器在杭州,结果打印在屏幕上,下次运行类似的语句再取的时候,那么我可以直接从这个客户端取数据就可以了。

简单介绍完这几种结果缓存,我们了解一下是怎么用的,什么时候可以用。

如果想用服务器结果缓存,那么SQL文本首先要一样,如果有绑定变量值,那么这个值也必须相同。为什么呢?大家想想,因为如果你变量传入的值不一样,会不会影响结果,那么查询的结果和前一次的结果不一样,那肯定不能从共享池拿之前的那个结果了。

首先建议不要在系统级打开结果缓存,因为如果你扫描的结果集很大的话,那不是把共享池撑暴了?一般都定制在查询的SQL中就可以了,很简单,提示里面加result_cache就可以了

举例: select /*+ gather_plan_statistics  result_cache */  * from mrpmusic.M2_TBL_ALBUM_SONG where id=1019;

SELECT * FROM table(dbms_xplan.display_cursor(null,null,’iostats last’));

876b052dgt9fn7g34qrgk4btxm  就是结果缓存的名字。

———————————————————————————————————–
| Id  | Operation                    | Name                       | Starts | E-Rows | A-Rows |   A-Time   |
———————————————————————————————————–
|   0 | SELECT STATEMENT             |                            |      1 |        |      1 |00:00:00.01 |
————————————————————————————————————
|   1 |  RESULT CACHE                | 876b052dgt9fn7g34qrgk4btxm |      1 |        |      1 |00:00:00.01 |
|   2 |   TABLE ACCESS BY INDEX ROWID| M2_TBL_ALBUM_SONG          |      0 |      1 |      0 |00:00:00.01 |
|*  3 |    INDEX UNIQUE SCAN         | SYS_C0017120               |      0 |      1 |      0 |00:00:00.01 |
———————————————————————————————————–

Predicate Information (identified by operation id):
—————————————————

可以通过v$result_cache_objects查询相关的缓存数据信息,cache_id也就是刚才执行计划的name,这里可以看到1是结过缓存了。

select status,CREATION_TIMESTAMP,ROW_COUNT,NAME,SCAN_COUNT from v$result_cache_objects where cache_id=’876b052dgt9fn7g34qrgk4btxm‘,可以查到结果缓存的相关信息,比如创建时间,花费的时间,存储的行数,被调用的次数,等等。

结果缓存是很容易失效的,如果结果集和从数据库查询出来的不一致,那就失效了,还有for update也会失效,上面介绍了对于某一特定语句进行了结果缓存,下面介绍一下动态参数控制服务器端结果缓存。

result_cache_max_size是指定结果缓存共享池的大小,这个值如果是0,那么就没这个特性了,一般都是自己根据共享池分配的,可以查看v$sgastat查看实际使用大小。

select name,sum(bytes) from v$sgastat where name like ’Result Cache%’ group by name;

result_cache_mode指定结果缓存使用那种方式,有manual 和force,当manual时,需要在语句添加hint / *+ result_cache */,如果是force,只要不加  / *+ no_result_cache */的,都会使用结果缓存。

result_cache_max_result指定任何单个结果集可以使用的result_cache_max_size的数量,这是单个sql使用的最大值,默认5%

result_cache_remote_expiration指定基于远程对象的结果集的临时有效期(单位为分钟)

PL/SQL函数结果缓存:

这个和服务器端结果缓存差不多,只不过他支持PL/SQL函数,记住,只有函数,其他的PL/SQL是不行的,而且要输入和输出要一致才可以。

举例: create or replace function f1(a in number)

return number

result_cache relies_on(t1)

is

o_var  number;

begin

select count(*)  into o_var from t1 where id=a;

return o_var;

end;

/

大家可以用以上的例子多调用几次,可以看出函数结果缓存的优势。select count(f1(1)) from t1;

使用PL/SQL函数结果缓存还有几个限制条件。结果缓存不能被以下函数所使用
1. 含有OUT和(或)IN OUT参数的函数。
2. 定义了使用调用者权限(invoker’s right)的函数。
3. 管道化的表函数(pipelined table function)。
4.从匿名块调用的函数
5.IN参数或者返回值含有以下类型的函数:LOB、REF CURSOR、对象和记录

6.随机函数,N:M关系

 

使用dbms_result_cache.flush可以清空结果缓存。

标签