11g新特性之结果集缓存
[@more@]结果集缓存(Result Set Caching)
缓存是提高性能的一个常用手段,可以说在Oracle数据库中,Cache无处不在。
Result Cache进一步又可以分为:Server Result Cache 和 Client Result Cache。前者通过服务器端SGA来缓存结果集,后者通过客户端来缓存结果集。
Client Result Cache:
在使用OCI应用程序时,可以通过客户端内存来缓存查询的结果集,缓存结果可以在所有session间共享,当查询反复执行时,查询结果可以直接从客户段的缓存中获得,从而极大地提高应用效率。
客户端结果集缓存并不使用服务器端的内存,不会对服务器的内存使用造成影响,这一点和Server Result Cache不同。
同Client Result Cache相关的视图主要有:
SQL> select * from dict where table_name like '%CLIENT_RESULT_CACHE%';
TABLE_NAME COMMENTS
------------------------------ -----------------------------------------
V$CLIENT_RESULT_CACHE_STATS Synonym for V_$CLIENT_RESULT_CACHE_STATS
GV$CLIENT_RESULT_CACHE_STATS Synonym for GV_$CLIENT_RESULT_CACHE_STATS
CLIENT_RESULT_CACHE_STATS$ Synonym for CRCSTATS_$
相关的参数有:
SQL> select * from dict where table_name like '%CLIENT_RESULT_CACHE%';client_result_cache_size设置为0,即为关闭Client Result Cache。
TABLE_NAME COMMENTS
------------------------------ ----------------------------------------
V$CLIENT_RESULT_CACHE_STATS Synonym for V_$CLIENT_RESULT_CACHE_STATS
GV$CLIENT_RESULT_CACHE_STATS Synonym for GV_$CLIENT_RESULT_CACHE_STATS
CLIENT_RESULT_CACHE_STATS$ Synonym for CRCSTATS_$
Server Result Cache:
Oracle Database 11g增加了关于数据缓存的功能栏。在过去,Oracle 数据库缓存数据库块。这些数据库块能够被缓存在很多区域,例如默认缓冲池、保持缓冲池和回收缓冲池。不过数据库的缓冲对象总是数据块,而构造块用于构建结果集。
从Oracle Database 11g开始,Oracle数据库也能够缓存结果集了。如果你要对变化缓慢甚至从不改变的数据不断地执行同一个查询,你就会发现这个全新的服务器端查询结果缓存功能非常管用。几乎所有的应用软件都能而且也将从这个特性中受益。
这个性能可以这样概括:当你执行一个查询时,Oracle Database 11g会先行查看这个查询的结果是不是已经有人计算过这个查询的结果并且将其缓存起来,如果是的,那么数据库就会从服务器端查询结果缓存中重新获取查询结果,而不会去集结所有的数据库块并整个的从头开始计算结果。执行第一次查询要花上和平常查询一样的时间(因为数据库是在计算结果),不过接下来的查询几乎可以算的上是即时的了,因为查询的结果是直接返回的,而不是计算然后返回的。
有观点认为这个特性与实时物化视图类似(just-in-time materialized view)。在Oracle8i Database Release 1中,Oracle引入了物化视图的概念。凭借这个,DBA们就可以创建概要表,例如,他们能够创建一个索引,而数据库优化器会识别到这个概要表的存在,而且如果可能的话,优化器会利用它来对查询作出应答,而不是查询并处理储存在基础表中的详细信息。这种运行方式很有用,但是相当的静态,更像是一个索引结构(indexing scheme.)。而Oracle Database 11g的服务器端查询结果缓存功能只利用一个缓存就能同时做到有效的创建并维持物化视图。
下面用例子来说明这个新功能
SQL> create table t as select * from dba_objects;
表已创建。
SQL> set autotrace traceonly;
SQL> set timing on;
SQL> select owner,count(*) from t group by owner order by 2;已选择29行。
已用时间: 00: 00: 00.61
执行计划
----------------------------------------------------------
Plan hash value: 81261667----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 70916 | 1177K| 290 (3)| 00:00:04 |
| 1 | SORT ORDER BY | | 70916 | 1177K| 290 (3)| 00:00:04 |
| 2 | HASH GROUP BY | | 70916 | 1177K| 290 (3)| 00:00:04 |
| 3 | TABLE ACCESS FULL| T | 70916 | 1177K| 284 (1)| 00:00:04 |
----------------------------------------------------------------------------Note
-----
- dynamic sampling used for this statement
统计信息
----------------------------------------------------------
48 recursive calls
0 db block gets
1091 consistent gets
1013 physical reads
0 redo size
1018 bytes sent via SQL*Net to client
427 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
29 rows processed
可以看到,花了0.61秒,physical reads 1013次,还有一次内存排序。我们再次执行这个命令。
SQL> select owner,count(*) from t group by owner order by 2;已选择29行。
已用时间: 00: 00: 00.06
执行计划
----------------------------------------------------------
Plan hash value: 81261667----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 70916 | 1177K| 290 (3)| 00:00:04 |
| 1 | SORT ORDER BY | | 70916 | 1177K| 290 (3)| 00:00:04 |
| 2 | HASH GROUP BY | | 70916 | 1177K| 290 (3)| 00:00:04 |
| 3 | TABLE ACCESS FULL| T | 70916 | 1177K| 284 (1)| 00:00:04 |
----------------------------------------------------------------------------Note
-----
- dynamic sampling used for this statement
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
1018 consistent gets
0 physical reads
0 redo size
1018 bytes sent via SQL*Net to client
427 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
29 rows processed
可以看到时间降为了 0.06秒,这是由于数据已经进入到内存,不需要再次从磁盘上读取了。所以 physical reads 为 0,执行速度也大为提升。但是consistent gets变化不大,sorts (memory) 也仍然存在。之后再执行几次,可以发现,最快也就是0.06秒了,这是最快的速度了。
现在我们看看使用最新的result cache 技术。使用 hint result_cache。
SQL> select /*+ result_cache */ owner,count(*) from t group by owner order by 2;
已选择29行。已用时间: 00: 00: 00.06
执行计划
----------------------------------------------------------
Plan hash value: 81261667--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 70916 | 1177K| 29
| 1 | RESULT CACHE | 5dgw29pr788n6bn48qjyq6sabc | | |
| 2 | SORT ORDER BY | | 70916 | 1177K| 29| 3 | HASH GROUP BY | | 70916 | 1177K| 29
| 4 | TABLE ACCESS FULL| T | 70916 | 1177K| 28
--------------------------------------------------------------------------------
Result Cache Information (identified by operation id):
------------------------------------------------------1 - column-count=2; dependencies=(MAS9I.T); parameters=(nls); name="select /*
Note
-----
- dynamic sampling used for this statement
统计信息
----------------------------------------------------------
4 recursive calls
0 db block gets
1087 consistent gets
0 physical reads
0 redo size
1018 bytes sent via SQL*Net to client
427 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
29 rows processed
第一次执行的时候,发现执行时间和统计信息和上一次的没什么区别,但是执行计划中可以发现有一个很大的区别,就是多了一行 | 1 | RESULT CACHE | 5dgw29pr788n6bn48qjyq6sabc | | | 。这说明就已经把结果存放到 cache 里面了。我们再次执行该语句
SQL> select /*+ result_cache */ owner,count(*) from t group by owner order by 2;
已选择29行。已用时间: 00: 00: 00.00
执行计划
----------------------------------------------------------
Plan hash value: 81261667--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 70916 | 1177K| 29
| 1 | RESULT CACHE | 5dgw29pr788n6bn48qjyq6sabc | | |
| 2 | SORT ORDER BY | | 70916 | 1177K| 29| 3 | HASH GROUP BY | | 70916 | 1177K| 29
| 4 | TABLE ACCESS FULL| T | 70916 | 1177K| 28
--------------------------------------------------------------------------------
Result Cache Information (identified by operation id):
------------------------------------------------------1 - column-count=2; dependencies=(MAS9I.T); parameters=(nls); name="select /*
Note
-----
- dynamic sampling used for this statement
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
1018 bytes sent via SQL*Net to client
427 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
29 rows processed
可以发现,消耗的时间变为了0,执行速度超快啊。在这个利用到Result Cache的查询中,consistent gets减少到0,直接访问结果集,不再需要执行SQL查询。这就是Result Cache的强大之处。现在我们另外开一个sqlplus,来执行这句sql。可以发现 ,仍然可以使用到cache中的数据。
当数据被修改后,cache中的数据能够被oracle自动清除,以保证数据的一致性。
服务器端结果集缓存使用Shared Pool中的内存来进行结果缓存,这部分内存使用可以通过v$sgastat视图来查询观察:
SQL> select * from v$sgastat where lower(name) like '%result%';
POOL NAME BYTES
------------ -------------------------- ----------
shared pool Result Cache: State Objs 2852
shared pool Result Cache 98396
shared pool Result Cache: Memory Mgr 128
shared pool Result Cache: Bloom Fltr 2048
shared pool Result Cache: Cache Mgr 112
和Result Cache相关的视图有:
SQL> select * from dict where table_name like '%RESULT_CACHE%';
TABLE_NAME COMMENTS
------------------------------ --------------------------------------------------------------------------------
V$CLIENT_RESULT_CACHE_STATS Synonym for V_$CLIENT_RESULT_CACHE_STATS
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
GV$CLIENT_RESULT_CACHE_STATS Synonym for GV_$CLIENT_RESULT_CACHE_STATS
CLIENT_RESULT_CACHE_STATS$ Synonym for CRCSTATS_$
11 rows selected
V$RESULT_CACHE_MEMORY 视图来看Cache的使用情况。
V$RESULT_CACHE_STATISTICS 可以查询Result Cache的统计信息。
V$RESULT_CACHE_OBJECTS 记录了Cache的对象。
DBMS_RESULT_CACHE 可以用于执行关于Result Cache的管理。
总结:如果结果集修改的频率不是很高,而且被查询的次数十分频繁,那么使用 Result Cache 技术可以极大地提升性能,但是不能滥用,由于存放result的内存大小有限制,只应该存放查询次数最频繁的Result,这个在开发的时候需要注意。
PS:在使用中发现,如果表是属于sys用户的时候,无法使用result cache技术。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/133835/viewspace-982057/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/133835/viewspace-982057/