2) % SQL with executions>1:此资料的计算公式是:100×(1-只执行一次的SQL数量/ 所有SQL数量),它是共享池中执行次数大于一次的SQL语句在所有SQL语句的百分比。这个数字当然越大越好。越大说明你的执行计划共享的越有效。
3) % Memory for SQL w/exec>1:此资料的计算公式是:100×(1-只执行一次的SQL所占内存/ 所有SQL所占内存)。此资料很好理解了,执行次数大于一次的语句所占内存与总语句所占内存的一个比例。
好了,STATSPACK中解析有关解析的资料就说的这里,软、硬解析的比例,在一定程度上代表了你的库缓存是否够大。还有一点,如果库缓存不够大,DBA是不能直接调大库缓存的,库缓存是共享池的重要部分之一。我们可以通过调节共享池的大小,来改变库缓存或共享池中其他部分的大小。
4.库缓存命中率与V$librarycache视图
在上面的Statspack报告中,已经提到了库缓存命中率这个概念,下面我们用视图说一下库缓存的命中率,视图中的信息比Statspack报告中的更详细一些。我们可以通过V$librarycache视图来查看库缓存的一些情况。在介绍此视图前,我们要先来介绍几个有关库缓存的概念。
(1)、库缓存句柄和库缓存内存块。
每一个进入库缓存的对象,在库缓存中都被按照本身内容分割成多块进行存贮,这就好像一只整鸡被分割成鸡腿、鸡翅、鸡爪等等。 Oracle这样做的目的是为了更灵活的内存管理,因为在内存寻找大块连续的内存,总比寻找小块连续内存更慢一些,这个我们在此处就不深入讨论了。继续刚才的话题,如果一个库缓存对象(如一条SQL语句的执行计划),它所占的内存被切割成4个小块,它们分别被存放在库缓存的各处,并且互不相连。为了将这4个小块组合起来,Oracle另外这个库缓存对象分配一小块内存,这块内存中存有其他4个小块内存的地址,并且,还有一些有关此库缓存对象的基本信息,如名字、类型等等,这块内存就叫库缓存对象句柄。
在访问库缓存对象时,比如软解析时,要从库缓存中读取执行计划。Oracle首先找到句柄,读取句柄中的信息,这就叫做一次库缓存Get。如果库缓存中不包括对象的句柄信息,Oracle就要重新在库缓存中分配内存、构造句柄,这就是库缓存句柄未命中(Get Miss)。相反,如果在库缓存中找到了对象句柄,就是库缓存句柄命中(Get Hit)。硬解析时,就会发生Get Miss。而软解析则是Get Hit。
在取出句柄中的其他内存块地址后,每访问一个内存块,都叫做一次库缓存Pin。如果相应的内存块已经不在内存中了,这就是Pin Miss,Pin的未命中。相反就是Pin Hit。
当库缓存中对象发生改变后,会引起其他一些对象的无效(Invalidation)。比如,你修改了一个表的结构,那么,选择了这个表的SQL语句的执行计划就会变的无效。其实大部分对表的DDL操作,都会造成相关SQL语句执行计划的无效。就连Grant(授权)、Revoke(撤消权限)这样看来跟执行计划耗无关系的操作,都会引起无效。如果有一个表TAB1,你发布了 “Grant 某权限on tab1 to 某用户”,或“revoke 某权限on tabl from 某用户”这样的操作,那么,所有和TAB1表有关的执行计划都将无效。无效之后,库缓存对象除句柄外的所有内存块,都将被清除。再使用到对象后,必须重新加载对象。如上例,如果你对TAB1使用了DDL语句,那么所有使用了TAB1表语句的执行计划都将无效,你再使用这些语句时,就必须重新硬解析语句。
因此,使用DDL语句是需要注意的,如果没有要求立即使用DDL,我们最好等到数据库并不繁忙的时刻,再执行DDL。作为DBA,这一点一定要牢记,除非要求立即执行,否则等到数据库并不繁忙时再执行任何DDL。
我们已经讲述了Get、Pin与它们的命中、未命中,还有什么是Invalidation和Reload。在OLTP 系统中,Get的命中率应该在90%之上。而Reload和Pin的次数的比值,应该小于1%。如果超出了这些数值范围,就说明库缓存的使用有问题。问题的原因主要有两个,没有使用绑定变量或是库缓存太小。不过Reload和Pin的比例过高,也可能是在繁忙时执行了DDL所导致的。
另外,V$librarycache的第一列是NAMESPACE,也就是名称空间。它相当于存储在库缓存中对象的类型。具体的名称空间是什么意思呢?就是对象的名字所在的范围,比如表和列的名字就不在一个范围内。也就是说表名和列名可以重复,还有用户名和表、列也不在同一范围内,用户名也可以和表、列名相同。我可以有个叫做AA的表,也可以有叫做AA的用户。这两个AA处在不同的范围内,也就明它们的名称空间不同。这就好像在北京有个电话号码是12345678,在上海也有个12345678,这两个电话号码虽然相同,但不会引起问题,因为它们在不同的范围内。这个范围,也可以说是类型。
我显示一下V$librarycache的所有行(列只有一部分):
SQL> select * from v$librarycache;
NAMESPACE GETS GETHITS GETHITRATIO PINS PINHITS
--------------- ---------- ---------- ----------- ---------- ----------
SQL AREA 21811 4149 .190225116 120258 105272
TABLE/PROCEDURE 25152 16372 .650922392 60649 46008
BODY 4360 4098 .939908257 5931 5537
TRIGGER 320 251 .784375 1655 1576
INDEX 453 128 .282560706 2065 1531
CLUSTER 755 728 .964238411