Oracle结果集缓存(Result Cache)--服务器、客户端、函数缓存

Oracle结果集缓存(Result Cache)--服务器、客户端、函数缓存


在11g中,Oracle提供告终果集缓存特性。该缓存是在共享内存中存储所有的结果集,若是一个查询SQL被执行,且它对应的结果集在缓存中,那么,该SQL的几乎所有开销均可以免。这些开销包括,解析时间、逻辑读、物理读和任意的一般可能会遭遇的争用。可是,在实际的状况中,结果集缓存仅在少数的状况下是有效的,缘由有以下几点:  面试

(1)有数据重叠的多个SQL会在缓存中保存冗余的数据。  算法

(2)对依赖对象的任何改变(包括对查询中引用的任意表)都会使整个缓存的结果集变为无效,结果集缓存最适合那些只读或接近只读的表。  sql

(3)大的结果集要么是由于结果集缓存太少不能放入,要么会强迫缓存中全部已存在的条件换出。为了防止这种状况发生,咱们必须限制结果集缓存仅用于较小的结果集。  数据库

(4)在缓存中快速并发的结果集的建立可能会致使结果集闩锁的争用。所以,结果集缓存的内容必须变得相对慢一些。缓存


结果集缓存由以下一些参数控制:  服务器

result_cache_mode :该参数用来控制结果集缓存的操做模式。OFF表示禁用,MANUAL表示只有使用了result_cahce提示的查询或对带有result_cache(mode force)属性的表访问的查询才会被缓存。FORCE表示全部合适的查询都会被缓存。  微信

result_cache_max_size:控制结果集缓存的大小,默认是共享池的1%。  网络

result_cache_max_result:单个结果集可以消耗的缓存的最大百分比。比这个值大的,将不能被缓存。  session

下面,咱们来进行一个配置:  并发

SQL> alter session set result_cache_mode = manual

  2  /


Session altered.


SQL> show parameters result_cache_max


NAME                                 TYPE

------------------------------------ ----------------------

VALUE

------------------------------

result_cache_max_result              integer

5

result_cache_max_size                big integer

1568K

SQL>

下面,咱们来运行一个结果集缓存的查询:  

SQL> create table t

  2  as

  3  select * from all_objects

  4  /


Table created.


SQL> alter table t add constraint t_pk primary key(object_id)

  2  /


Table altered.


SQL> exec dbms_stats.gather_table_stats(user,'t',cascade=>true)


PL/SQL procedure successfully completed.


SQL> set autotrace traceonly

SQL> select /*+result_cache*/ *

  2  from t

  3  where object_id <= 300

  4  /



Execution Plan

----------------------------------------------------------

Plan hash value: 3772518221


-------------------------------------------------------------------------------- ---------------------------

| 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 |

-------------------------------------------------------------------------------- ---------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


   3 - access("OBJECT_ID"<=300)


Result Cache Information (identified by operation id):

------------------------------------------------------


   1 - column-count=15; dependencies=(DJP01.T); attributes=(ordered); 

        name="select /*+result_cache*/ *

                     from t

                   where object_id <= 300"


Statistics

----------------------------------------------------------

           1  recursive calls

          0  db block gets

           5  consistent gets

          0  physical reads

          0  redo size

       1649  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)

          5  rows processed


SQL> set autotrace off

SQL>

说明:当使用结果集缓存的时候,会在执行计划中看到上述的黑体部分的信息。其中,name列中的值,是结果集缓存在内存当中的一个地址。这时,上述对应的查询结果已经被缓存。  

下面,咱们对其再次进行一个访问:  

SQL> set autotrace traceonly

SQL> select *

  2  from t

  3  where object_id <= 300

  4  /



Execution Plan

----------------------------------------------------------

Plan hash value: 3772518221


-------------------------------------------------------------------------------- ----

| Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time    |

-------------------------------------------------------------------------------- ----

|   0 | SELECT STATEMENT            |      |   100 |  8600 |     4   (0)| 00:00: 01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| T    |   100 |  8600 |     4   (0)| 00:00: 01 |

|*  2 |   INDEX RANGE SCAN          | T_PK |   100 |       |     2   (0)| 00:00: 01 |

-------------------------------------------------------------------------------- ----


Predicate Information (identified by operation id):

---------------------------------------------------


   2 - access("OBJECT_ID"<=300)



Statistics

----------------------------------------------------------

           1  recursive calls

          0  db block gets

           5  consistent gets

          0  physical reads

          0  redo size

       1770  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)

          5  rows processed


SQL> select /*+result_cache*/ *

  2  from t

  3  where object_id <= 300

  4  /



Execution Plan

----------------------------------------------------------

Plan hash value: 3772518221


-------------------------------------------------------------------------------- ---------------------------

| 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 |

-------------------------------------------------------------------------------- ---------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


   3 - access("OBJECT_ID"<=300)


Result Cache Information (identified by operation id):

------------------------------------------------------


   1 - column-count=15; dependencies=(DJP01.T); attributes=(ordered); name="sele

ct /*+result_cache*/ *

from t

where object_id <= 300"



Statistics

----------------------------------------------------------

           0  recursive calls

          0  db block gets

           0  consistent gets

          0  physical reads

          0  redo size

       1649  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)

          5  rows processed


SQL> set autotrace off

SQL>

说明;在第一次使用result_cache提示进行查询时,对结果集进行了缓存。接一下来的查询当中,我分别使用了无result_cache提示和有result_cache提示的查询进行了对比。对比发现,无提示的SQL仍然进行了SQL的相关处理(好比,解析、逻辑读取等),尽管咱们对结果集缓存了亦是如此。这是由于该查询中没有使用result_cache提示,Oracle没法识别该查询对应的结果集是否被缓存,于是使用了常规SQL流程。只胡对结果集进行了缓存,并且必须是彻底相同的SQL(好比第一次查询使用了提示,第二次查询她必须使用),这样,才能利用结果集缓存中的数据。如上述最后一个查询所示。  


咱们可使用v$result_cache_statistics视图来查看结果集缓存的统计数据,SQL以下:  

SQL> column name format a30

SQL> column value format a10

SQL> select name,value

  2  from v$result_cache_statistics

  3  /


NAME                           VALUE

------------------------------ ----------

Block Size (Bytes)             1024

Block Count Maximum            1568

Block Count Current            32

Result Size Maximum (Blocks)   78

Create Count Success           1

Create Count Failure           0

Find Count                     1

Invalidation Count             0

Delete Count Invalid           0

Delete Count Valid             0

Hash Chain Length              1


11 rows selected.


SQL>

说明:Create Count Success表示建立成功的结果集缓存的个数。Find Count 表示在结果集缓存中发现查询的个数。Invalidation Count表示当DML改变一个依赖对象的内容的时,无效的结果集缓存的个数。Delete Count Invalid表示为了给新的结果集腾出空间,从内存中删除无效结果集的个数。  


在实际当中,只有少部分结果集是有效的,并且大部分是比由那些没有被使用就被换出内存的结果集组成。咱们能够经过查询执行计划中包含result cache操做且在缓存里的那些SQL的统计数据,咱们还能够检查单个结果集的效率。SQL以下:  

SQL> with result_cache

  2  as(

  3  select cache_id,count(*) cache_sets,sum(scan_count) rc_hits

  4  from v$result_cache_objects

  5  group by cache_id

  6  )

  7  select /*+ordered*/ s.sql_id,s.executions,o.cache_sets,o.rc_hits,

  8         round(s.rows_processed/executions) avg_rows,buffer_gets,

  9         round(buffer_gets/(executions-o.rc_hits)) avg_gets_nocache,

 10         round(buffer_gets/(executions-o.rc_hits)*o.rc_hits) estd_saved_gets,

 11         s.sql_text

 12  from v$sql_plan p join result_cache o on (p.object_name = o.cache_id)

 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  /


SQL_ID                     EXECUTIONS CACHE_SETS    RC_HITS   AVG_ROWS

-------------------------- ---------- ---------- ---------- ----------

BUFFER_GETS AVG_GETS_NOCACHE ESTD_SAVED_GETS

----------- ---------------- ---------------

SQL_TEXT

--------------------------------------------------------------------------------

6735aa1xanfym                       2          1          1          5

          5                5               5

select /*+result_cache*/ * from t where object_id <= 300



SQL>


当DML语句修改了查询涉及的任意一个依赖的表时,缓存的结果集会被从缓存中消除。咱们能够用以下的SQL来查看缓存中的查询和依赖的对象,SQL以下:  

SQL> select /*+ordered*/ max(o2.name) cache_object,count(*) sets_cached,

  2        o1.cache_id dependency

  3  from v$result_cache_dependency d join v$result_cache_objects o1

  4       on ( d.depend_id = o1.id) join v$result_cache_objects o2

  5       on (d.result_id = o2.id)

  6  group by o1.cache_id

  7  /


CACHE_OBJECT

--------------------------------------------------------------------------------

SETS_CACHED

-----------

DEPENDENCY

--------------------------------------------------------------------------------

select /*+result_cache*/ *

from t

where object_id <= 300

          1

DJP01.T



SQL>





众所周知,内存的访问速度远远高于磁盘,把常用的数据存放于内存中来提升检索速度已不是什么新鲜事了。Cache 是内存中的一片区域,也叫缓存,现在关系型数据库正是利用这一种重要机制,使得访问数据库的性能日新月异。

Result Cache简述

数据库在构建一个SQL查询结果时,不只须要在访问数据上消耗时间,数据的排序、聚合以及链接操做也会消耗一部分时间。对此Oracle 在11g R1版本中引入了Result Cache(结果集缓存),目的就是将查询结果直接放入内存中,节省构建结果集所花费的时间和资源。引擎能够直接返回结果,而没必要在缓存中读取数据.

咱们能够把SQL执行归纳为三个阶段:

1.从存储获取数据到内存(对于还没有在缓存中的数据)

2.对缓存数据集进行筛选

3.返回结果集给客户端

Result Cache在启用的状况下,不只会把结果集返回给客户端,并且还会把结果集缓存在Shared Pool特定的一块区域内。当任何客户端执行相似SQL返回相同结果时,Oracle会跳过1和2直接从Result Cache中返回结果,大大提升了性能。

Result Cache能够分为:Server Result Cache(服务器端结果集缓存) 和 Client Result Cache (客户端结果集缓存)

Server Result Cache,经过在Shared Pool中单独分配一块内存来进行结果缓存。

Client Result Cache,经过应用程序层配置,缓存结果集位于客户端内存中。并能够在全部Session间共享,当查询被反复执行时,查询结果能够直接从客户端的缓存中得到,从而极大地提升了应用效率。

Result Cache 特性能够经过一些动态参数进行控制,好比用以定义结果集的内存池的大小、触发的方式等。

默认状况下Result Cache是开启的,全部开发人员均可以使用该特性。

1.表级别使用

2.语句级别使用

默认状况下,若是基础表发生改变,Oracle会将Result Cache中的结果集设置为无效,使得客户端不会从结果缓存中获取过期的数据。当查询运行时,失效的Result Cache结果集将从新被缓存,而后在提交DML发生数据修改时再次被设置为无效。

Result Cache使用监控(相关查看包及视图)

v$result_cache_statistics 内存统计数据

v$result_cache_object 对象跟属性

v$result_cache_dependency 显示结果的依赖关系

v$result_cache_memory 显示内存块及统计数据

Result Cache的影响

Result Cache的读取和修改与其余Oracle部份内存池的读取修改状况相似,也是经过Latch锁进行保护,读取缓存池时须要持有共享锁,修改时(用于添加新的结果集或使现有结果集无效)须要持有排他锁,以免其余会话同时访问。

所以频繁的更新Result Cache中对应的表格会引发Latch锁的争用(特别是RC Latch)

若是在某些对象上几乎全部查询都同时并发使用Result Cache,状况会更糟。

下面以一个具体的案例介绍:

某客户从AIX平台迁移到x86稳定运行半个月后,高峰期时常出现卡顿,提取故障点的awr及ash报告。从上述等待事件能够看出数据库大部分时间都花在enq: TX – row lock contention和latch free上。

第一反应可能以为是enq: TX – row lock contention引发的故障,但随后进一步沟通发现,从迁移以后程序代码并没有变化。既然业务逻辑没有改变TX锁引发这次故障可能性不大,初步断定是因为latch free 使得TX锁加重。继续查看latch free 相关的信息。

latch的信息统计,定位主要元凶是Result Cache:RC Latch。

查看result相关参数其中result_cache_mode为force,解决办法能够直接把result_cache_mode改为manual或直接禁用result cache 设置result_cache_max_size为0。

结论

Result Cache是Oracle又一个进步,能大幅提高性能,但也像其余特性同样,不是全部的会话都适用。






1、Result Set Caching 说明


一、概述:Oracle 从11g开始引入告终果集缓存(result cache)的新特性,用于存储常用的SQL语句和函数的查询结果,未来语句再执行的时候,oracle直接的访问内存获得结果

二、优势:重用相同的结果集,减小逻辑IO,提升系统性能

三、分类:oracle数据库引擎提供了三种结果集缓存,包括:服务器查询结果集缓存、pl/sql函数结果集缓存和客户端结果集缓存

四、应用场合:访问多行返回少数行的语句,很是适合只读、读>>写、典型OLTP等系统的功能;ORACLE建议应用仅仅对read only的表中使用result cache缓存功能

五、影响因素:在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

六、使用限制: 

             (1)查询使用非肯定性的函数,序列和临时表的结果集不会被缓存

             (2)查询违反了读一致性时结果集将不会被缓存
             (3)引用数据字典视图的查询的结果集不会被缓存
             (4)查询结果集大于可用缓存结果集可用空间的不被缓存;采用LRU算法来管理result cache。

2、服务器端结果集缓存


一、 相关参数说明

影响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
----------
        .8

小结:由上可知,RESULT_CACHE_MAX_SIZE三种默认取值刚好对应的是数据库内存的三种管理模式(AMM、ASMM和MSMM);手动设置时,最大值为shared_pool_size的80%

RESULT_CACHE_MAX_RESULT

限制单个result所能占据query cache的最大百分比大小;默认是5%

RESULT_CACHE_REMOTE_EXPIRATION

设置远程数据库结果集缓存过时的时间,以分钟为单位,默认值为0不缓存远程数据库结果集

二、相关视图说明

V$RESULT_CACHE_STATISTICS:列出各类缓存设置和内存使用统计数据。
    V$RESULT_CACHE_MEMORY:列出全部的内存块和相应的统计信息。
   V$RESULT_CACHE_OBJECTS:列出全部的对象(缓存的结果和依赖的对象)和它们的属性。
V$RESULT_CACHE_DEPENDENCY:列出缓存的结果和依赖对象间的依赖详情。

三、相关的包: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
一、设置RESULT_CACHE_MODE为FORCE
二、根据内存管理方式调整相关参数,设置RESULT_CACHE_MAX_SIZE大小
三、检查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、服务端缓存


1.服务器端的Result Cache Memorey由两部分组成。
(1)SQL Query Result Cache:存储SQL查询的结果集。
(2)PL/SQL Function Result Cache:用于存储PL/SQL函数的结果集。


 


2.相关的初始化参数:


SQL> show parameter result


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


 


带client的是客户端的参数,剩下的是服务端的相关参数。


2.1 首先,服务端的结果集缓存的开关,是参数result_cache_max_size。当result_cache_max_size=0的时候,表明不启用结果集缓存。


它的大小,默认值取决于其它内存设置(memory_target的0.25% 或sga_target 的0.5% 或shared_pool_size 的1%)


2.2 其次,result_cache_mode 用于控制Server Result cache的模式


result_cache_mode 有3个值:auto、manual、force


若是设置的值为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的。


 


3.相关视图


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.


 


4.2 FLUSH: 清空整个结果缓存的内容。
 
4.3 INVALIDATE: 使结果缓存中一个特定对象的缓存结果无效。
 
4.4 INVALIDATE_OBJECT: 根据缓存ID使一特定结果缓存无效。


 


5.实验:


复制代码
SQL> create table test as select * from dba_objects;


Table created.


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"




Note
-----
   - dynamic sampling used for this statement (level=2)




Statistics
----------------------------------------------------------
         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"




Note
-----
   - dynamic sampling used for this statement (level=2)




Statistics
----------------------------------------------------------
          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.


SQL> 
复制代码
再来看看相应的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.


SQL> 
复制代码
注意到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'
  2  ;


NAME
------------------------------
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,以下所示




SQL> select * from v$latchname where name like 'Result Cache%';


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环境。


 


2、客户端查询结果集缓存


假设有这样一个情形:客户端须要经过慢速网络连接调用同一数据。尽管数据库能够当即将结果从缓存发送到客户端,但结果必须经过线路传送到客户端,这就增长了总体执行时间。如今有一些专门的中间件框架(如 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)
Note
-----
  - 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
SQL>

这个功能对静态表很是有用














About Me

...............................................................................................................................

● 本文整理自网络

● 本文在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群,学习最实用的数据库技术。

ico_mailme_02.png
DBA笔试面试讲解
欢迎与我联系


来自 “ ITPUB博客 ” ,连接:http://blog.itpub.net/26736162/viewspace-2140589/,如需转载,请注明出处,不然将追究法律责任。

1、Result Set Caching 说明


一、概述:Oracle 从11g开始引入告终果集缓存(result cache)的新特性,用于存储常用的SQL语句和函数的查询结果,未来语句再执行的时候,oracle直接的访问内存获得结果

二、优势:重用相同的结果集,减小逻辑IO,提升系统性能

三、分类:oracle数据库引擎提供了三种结果集缓存,包括:服务器查询结果集缓存、pl/sql函数结果集缓存和客户端结果集缓存

四、应用场合:访问多行返回少数行的语句,很是适合只读、读>>写、典型OLTP等系统的功能;ORACLE建议应用仅仅对read only的表中使用result cache缓存功能

五、影响因素:在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

六、使用限制: 

             (1)查询使用非肯定性的函数,序列和临时表的结果集不会被缓存

             (2)查询违反了读一致性时结果集将不会被缓存
             (3)引用数据字典视图的查询的结果集不会被缓存
             (4)查询结果集大于可用缓存结果集可用空间的不被缓存;采用LRU算法来管理result cache。

2、服务器端结果集缓存

一、 相关参数说明 影响result cache开启使用的两个参数:result_cache_mode和result_cache_max_sizeRESULT_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 ----------         .8 小结:由上可知,RESULT_CACHE_MAX_SIZE三种默认取值刚好对应的是数据库内存的三种管理模式(AMM、ASMM和MSMM);手动设置时,最大值为shared_pool_size的80%RESULT_CACHE_MAX_RESULT 限制单个result所能占据query cache的最大百分比大小;默认是5%RESULT_CACHE_REMOTE_EXPIRATION 设置远程数据库结果集缓存过时的时间,以分钟为单位,默认值为0不缓存远程数据库结果集 二、相关视图说明 V$RESULT_CACHE_STATISTICS:列出各类缓存设置和内存使用统计数据。     V$RESULT_CACHE_MEMORY:列出全部的内存块和相应的统计信息。    V$RESULT_CACHE_OBJECTS:列出全部的对象(缓存的结果和依赖的对象)和它们的属性。 V$RESULT_CACHE_DEPENDENCY:列出缓存的结果和依赖对象间的依赖详情。 三、相关的包: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一、设置RESULT_CACHE_MODE为FORCE 二、根据内存管理方式调整相关参数,设置RESULT_CACHE_MAX_SIZE大小 三、检查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、服务端缓存 1.服务器端的Result Cache Memorey由两部分组成。 (1)SQL Query Result Cache:存储SQL查询的结果集。 (2)PL/SQL Function Result Cache:用于存储PL/SQL函数的结果集。   2.相关的初始化参数: SQL> show parameter result 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   带client的是客户端的参数,剩下的是服务端的相关参数。 2.1 首先,服务端的结果集缓存的开关,是参数result_cache_max_size。当result_cache_max_size=0的时候,表明不启用结果集缓存。 它的大小,默认值取决于其它内存设置(memory_target的0.25% 或sga_target 的0.5% 或shared_pool_size 的1%) 2.2 其次,result_cache_mode 用于控制Server Result cache的模式 result_cache_mode 有3个值:auto、manual、force 若是设置的值为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的。   3.相关视图 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.   4.2 FLUSH: 清空整个结果缓存的内容。   4.3 INVALIDATE: 使结果缓存中一个特定对象的缓存结果无效。   4.4 INVALIDATE_OBJECT: 根据缓存ID使一特定结果缓存无效。   5.实验: 复制代码 SQL> create table test as select * from dba_objects; Table created. 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" Note -----    - dynamic sampling used for this statement (level=2) Statistics ----------------------------------------------------------          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" Note -----    - dynamic sampling used for this statement (level=2) Statistics ----------------------------------------------------------           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. SQL>  复制代码 再来看看相应的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. SQL>  复制代码 注意到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'   2  ; NAME ------------------------------ 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,以下所示 SQL> select * from v$latchname where name like 'Result Cache%'; 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环境。   2、客户端查询结果集缓存 假设有这样一个情形:客户端须要经过慢速网络连接调用同一数据。尽管数据库能够当即将结果从缓存发送到客户端,但结果必须经过线路传送到客户端,这就增长了总体执行时间。如今有一些专门的中间件框架(如 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才能使用。

相关文章
相关标签/搜索