当构建生产系统,我们的一般做法是首先根据经验给出一个共享池尺寸,然后,在一定的工作载荷压力下,检查相关的统计
来检查共享池的效率。
共享池的效率对于不同的应用来说是不同的。对于大多数OLTP应用系统,共享池尺寸将直接影响系统的性能。因为SQL、
PL/SQL的硬解析将导致资源的浪费和共享池栓(资源锁)的争用。但对于决策支持(DSS)系统,其性能代价相对较小。
库缓存的使用效率可以通过命中率的统计来进行分析。如前所述,共享池中的库缓存用来保证多次执行的SQL语句将被
缓存起来,以避免硬解析。我们可以通过V$LIBRARYCACHE动态视图来得到关于库缓存的命中率信息,包括SQL的重载相关信息、
SQL解析结果不可用的相关信息。下面的示例查询了当前库缓存的使用状态:
SQL>SELECT NAMESPACE,PINS,PINHITS,RELOADS,INVALIDATIONS FROM V$LIBRARYCACHE ORDER BY NAMESPACE;
SQL> SELECT NAMESPACE,PINS,PINHITS,RELOADS,INVALIDATIONS FROM V$LIBRARYCACHE ORDER BY NAMESPACE;
NAMESPACE PINS PINHITS RELOADS INVALIDATIONS
--------------- ---------- ---------- ---------- -------------
BODY 8851836 8756370 61901 0
CLUSTER 230680 212963 13929 0
INDEX 231760 172036 2933 0
JAVA DATA 0 0 0 0
JAVA RESOURCE 0 0 0 0
JAVA SOURCE 0 0 0 0
OBJECT 0 0 0 0
PIPE 0 0 0 0
SQL AREA 3145910657 2031153447 2855257 440049
TABLE/PROCEDURE 433904619 429595986 2167680 0
TRIGGER 2732465 2637826 90366 0
其中,RELOAD列表示SQL被重新解析的累积次数,INVALIDATION列表示解析结果不可用的累积次数。这两个值都应接近零。
另一个关键的统计是在系统运行峰值状态下共享池中自由内存的数量。自由内存数量应该劲量低,以使其被充分利用,
避免重载(RELADS)的发生。该数值通过V$SGASTAT视图进行查询,列入下面的查询示例。
SQL>select * from V$SGASTAT where name like '%free memory%';
POOL NAME BYTES
------------ -------------------------- ----------
shared pool free memory 2180229864
large pool free memory 15701144
java pool free memory 16777216
上面查询了系统最近一次启动系统后的SQL重载次数、失效次数、自由空间等统计。这些统计和库缓存的命中率、栓争用信息
结合起来,就可以判断库缓存的利用率了。
动态性能视图V$LIBRARYCAHCE统计了系统自启动后累积的关于库缓存使用的信息。该视图中每行显示了存储在库缓存在库缓存中的
信息。该视图中每行显示了存储在库缓存中的各类对象和库缓存使用统计。下列查询显示了当前系统库缓存的使用统计:
SQL>SELECT NAMESPACE,PINS,PINHITS,PINHITRATIO,RELOADS,INVALIDATIONS from V$LIBRARYCACHE;
SQL> SELECT NAMESPACE,PINS,PINHITS,PINHITRATIO,RELOADS,INVALIDATIONS from V$LIBRARYCACHE;
NAMESPACE PINS PINHITS PINHITRATIO RELOADS INVALIDATIONS
--------------- ---------- ---------- ----------- ---------- -------------
SQL AREA 44904 41857 .93214413 950 1
TABLE/PROCEDURE 14568 9677 .664264141 1078 0
BODY 2038 1948 .955839058 55 0
TRIGGER 292 276 .945205479 6 0
INDEX 101 6 .059405941 38 0
CLUSTER 373 359 .962466488 6 0
OBJECT 0 0 1 0 0
PIPE 0 0 1 0 0
JAVA SOURCE 0 0 1 0 0
JAVA RESOURCE 0 0 1 0 0
JAVA DATA 0 0 1 0 0
因此,分析上面的结果,SQL的执行(SQL AREA 命名空间)有 44904次(PINS列)其中41857次(PINHITS 列)可以从库中获得,命中率(PINHITRATIO列)为93.21%以上。
结合共享池中自由内存量的查询(查询V$SGASTAT中关于SGA的分配统计信息),可以看到共享池有 2180229864字节的自由内存。因此,
本例中增加共享池的大小,将不会对系统效率产生边际效益。
共享池中的另外一个数据结构是数据字典缓存。一般而言,如果共享池满足库缓存的需求,则数据字典缓存部分也同样够用,无须单独
考虑其大小。和库缓存一样,字典缓存在系统启动初期是空白的,随着数据字典数据不断的被读入缓存,字典缓存的使用趋于稳定。
在一定的运行时间之后,大多数常用数据字典信息将被缓存在字典缓存区域。
动态性能视图V$ROWCACHE可以用来显示字典缓存的使用情况。该视图中每一行数据反映一种数据字典的统计,统计值从最近一次的实例
启动开始累计。该视图的下面四列反映了最常用信息:
PARAMETER:数据字典项
GETS:通过数据字典缓存对数据字典请求的获得
GETMISSES:不能通过数据字典缓存获得数据的请求总数,即丢失总数。
MODIFICATIONS:在数据字典缓存中数据项被更新的次数。
下面是一个常用来查看关于数据字典缓存使用统计的查询,并以命中率的形式查看其使用率:
SQL> SELECT parameter,
sum(gets),
sum(getmisses),
100*sum(gets - getmisses)/sum(gets) get_rate,
sum(modifications) modified
from v$rowcache
where gets>0
group by parameter;
PARAMETER SUM(GETS) SUM(GETMISSES) GET_RATE MODIFIED
-------------------------------- ---------- -------------- ---------- ----------
dc_tablespaces 5827 7 99.8798696 0
dc_awr_control 193 1 99.4818653 7
dc_object_grants 16 2 87.5 0
dc_histogram_data 4254 642 84.9083216 0
dc_rollback_segments 1040 11 98.9423077 31
dc_sequences 10 5 50 10
dc_usernames 1185 7 99.4092827 0
dc_segments 2991 579 80.6419258 8
dc_objects 6028 679 88.7358991 73
dc_histogram_defs 10585 2783 73.7080775 0
dc_users 7323 9 99.8770995 0
PARAMETER SUM(GETS) SUM(GETMISSES) GET_RATE MODIFIED
-------------------------------- ---------- -------------- ---------- ----------
outstanding_alerts 137 14 89.7810219 2
dc_files 6 6 0 0
dc_object_ids 10653 725 93.1944053 56
dc_global_oids 517 31 94.0038685 0
dc_profiles 171 1 99.4152047 0
16 rows selected.
SQL>
上面的查询结果显示了当前数据字典缓存具有较高的命中率。但某些项的值并不高。这可能和开机时间不常有关。
下面的一个示例综合计算了数据字典缓存的整体命中率:
SQL>SELECT (SUM(GETS - GETMISSES - FIXED))/SUM(GETS) "Data Dict Hint Rate" from v$ROWCACHE;
Data Dict Hint Rate
-------------------
.890128386
显然,在一般情况下增加共享池的内存总量将增加库缓存和数据字典缓存的可使用量,可能有利于增加共享池的命中率。
Oracle中没有关于库缓存和字典缓存的初始化参数。增加共享池(初始化参数 SHARED_POOL_SIZE)的值后,数据字典缓存也
同时得到了增加。一般而言,如果库缓存、字典缓存的命中率低于90%,则考虑增加初始化参数SHARED_POOL_SIZE的值。
这里面要注意增加初始化参数 SHARED_POOL_SIZE所能带来的边际效益。当SHARED_POOL_SIZE大到一定程度时,例如300MB,
大多数系统的库缓存命中率及数据字典缓存的命中率都会达到一种稳定的状态。再增加此参数的值,将不能带来实际的效益。
SQL 缓存设置参数
在库缓存命中率保持较高的情况下,设置CURSOR_SPACE_FOR_TIME 参数可以起到加快SQL执行速度的作用。该参数的作用是
指定那些已被缓存的SQL语句及其执行计划、已编译可执行代码,是否可被“置换出”库缓存,以容纳新产生的SQL。该参数默认为
false:
SQL>show parameter CURSOR_SPACE_FOR_TIME
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
cursor_space_for_time boolean FALSE
这表明,当库缓存需要空间来容纳新的SQL时,可以释放当前存储在库缓存中的SQL来维护空闲空间,即便这条SQL语句当前处于被
引用状态(当前应用系统正在使用这条被缓存的SQL)
因此,是否设置该参数为true,取决于系统库缓存的命中率。在保持命中率的前提下,可以考虑设置这个参数,这将提高Oracle
的SQL执行效率。
下面查询当前数据库得到库缓存命中率,其结果显示缓存命中率较高:
SQL>SELECT NAMESPACE,PINS,PINHITS,PINHITRATIO ,RELOADS,INVALIDATIONS from v$librarycache
order by namespace;
如果命中率高,就可以使用下面命令设置该参数为true
SQL>alter system set cursor_space_for_time=true scope=spfile;
需要注意的是,当库缓存命中率较低时,不可以进行这样的设置,因为这会造成库缓存调度错误,进而引发Oracle执行SQL中的错误。