结果缓存,缓存到那里呢?共享池! 也就是说把查询出来的结果集共享到共享池。这样不用解析,不用执行,直接从共享池读取这个结果集就可以,称之为结果缓存。
首先介绍第一种结果缓存:服务器结果缓存
比如一个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可以清空结果缓存。