Oracle内存全面分析(3)

1.1.3.3.            Buffer Cache的重要视图

关于Buffer Cache,oracle提供一些重要视图,用于查询关于Buffer Cache的重要信息,为调整Buffer Cache、提高性能提供参考。下面一一介绍它们

·        v$db_cache_advice

上面我们提到了Oracle的建议器,其中有一个针对Buffer Cache的建议器。在我们设置了参数db_cache_advice为TRUE后,经过一段时间的系统运行,Oracle收集到相关统计数据,并根据一定的数学模型,预测出DB_CACHE_SIZE在不同大小情况的性能数据。我们就可以由视图V$DB_CACHE_ADVICE查出这些数据,并根据这些数据调整DB_CACHE_SZIE,使系统性能最优。

下面是关于这个视图的结构描述:

字段

数据类型

描述

ID

NUMBER

缓冲池标识号(从1到8,1-6对应于DB_nK_CACHE_SIZE,DB_CACHE_SIZE与系统标准块尺寸的序号相关,如DB_BLOCK_SIZE为8K,则DB_CACHE_SIZE的标识号为3(2,4,8…)。7是DB_KEEP_CACHE_SIZE,8是DB_RECYCLE_CACHE_SIZE)

NAME

VARCHAR2(20)

缓冲池名称

BLOCK_SIZE

NUMBER

缓冲池块尺寸(字节为单位)

ADVICE_STATUS

VARCHAR2(3)

建议器状态:ON表示建议器在运行;OFF表示建议器已经关闭。当建议器关闭了,视图中的数据是上一次打开所统计得出的。

SIZE_FOR_ESTIMATE

NUMBER

预测性能数据的Cache大小(M为单位)

SIZE_FACTOR

NUMBER

预测的Cache大小因子(即与当前大小的比例)

BUFFERS_FOR_ESTIMATE

NUMBER

预测性能数据的Cache大小(缓冲块数)

ESTD_PHYSICAL_READ_FACTOR

NUMBER

这一缓冲大小时,物理读因子,它是如果缓冲大小为SIZE_FOR_ESTIMATE时,建议器预测物理读数与当前实际物理读数的比率值。如果当前物理读数为0,这个值为空。

ESTD_PHYSICAL_READS

NUMBER

如果缓冲大小为SIZE_FOR_ESTIMATE时,建议器预测物理读数。

 

下面是从这个视图中查询出来的数据:

SQL> select size_for_estimate, estd_physical_read_factor, estd_physical_reads
  2  from v$db_cache_advice
  3  where name = 'DEFAULT';
 
SIZE_FOR_ESTIMATE ESTD_PHYSICAL_READ_FACTOR ESTD_PHYSICAL_READS
----------------- ------------------------- -------------------
               16                    2.0176             6514226
               32                    1.7403             5619048
               48                    1.5232             4917909
               64                    1.3528             4367839
               80                    1.2698             4099816
               96                    1.1933             3852847
              112                    1.1443             3694709
              128                    1.1007             3553685
              144                    1.0694             3452805
              160                    1.0416             3362964
              176                    1.0175             3285085
              192                         1             3228693
              208                    0.9802             3164754
              224                    0.9632             3109920
              240                    0.9395             3033427
              256                    0.8383             2706631
              272                    0.7363             2377209
              288                     0.682             2202116
              304                    0.6714             2167888
              320                    0.6516             2103876
 
20 rows selected

 

当前我们的DB_CACHE_SIZE为192M,可以看到,它的物理读因子为1,物理读数为3228693。那么如何根据这些数据调整DB_CACHE_SIZE呢?给出一个方法,找到变化率较平缓的点作为采用值。因为建议器做预测是,DB_CACHE_SIZE的预测值的增长步长是相同的,是16M。我们按照这一步长增加DB_CACHE_SIZE,如果每次增加物理读降低都很明显,就可以继续增加,直到物理读降低不明显,说明继续增加DB_CACHE_SIZE没有太大作用。当然,性能和可用资源是天平的两端,你需要根据自己系统的实际情况调整。

上面的例子中,我们可以考虑将DB_CACHE_SIZE调整到288M。因为在288M之前,物理读因子变化都比较大,而从288M到304M以后,这个因子变化趋缓。用一个二维图可以更容易看出这个变化来:

这一视图作为调整DB_CACHE_SIZE以提高性能有很大参考价值。但衡量Buffer Cache是否合适的重要指标还是我们前面提到的缓存命中率(Buffer Hit),而影响缓存命中率往往还有其他因素,如性能极差的SQL语句。

·        V$BUFFER_POOL

这一视图显示了当前实例中所有缓冲池的信息。它的结构如下:

字段

数据类型

描述

ID

NUMBER

缓冲池ID,和上面视图描述相同。

NAME

VARCHAR2(20)

缓冲池名称

BLOCK_SIZE

NUMBER

缓冲池块尺寸(字节为单位)

RESIZE_STATE

VARCHAR2(10)

缓冲池当前状态。

STATIC:没有被正在调整大小

ALLOCATING:正在分配内存给缓冲池(不能被用户取消)

ACTIVATING:正在创建新的缓存块(不能被用户取消)

SHRINKING:正在删除缓存块(能被用户取消)

CURRENT_SIZE

NUMBER

缓冲池大小(M为单位)

BUFFERS

NUMBER

当前缓存块数

TARGET_SIZE

NUMBER

如果正在调整缓冲池大小(即状态不为STATIC),这记录了调整后的大小(M为单位)。如果状态为STATIC,这个值和当前大小值相同。

TARGET_BUFFERS

NUMBER

如果正在调整缓冲池大小(即状态不为STATIC),这记录了调整后的缓存块数。否则,这个值和当前缓存块数相同。

PREV_SIZE

NUMBER

前一次调整的缓冲池大小。如果从来没有调整过,则为0。

PREV_BUFFERS

NUMBER

前一次调整的缓存块数。如果从来没有调整过,则为0。

LO_BNUM

NUMBER

9i后已经废弃字段

HI_BNUM

NUMBER

9i后已经废弃字段

LO_SETID

NUMBER

9i后已经废弃字段

HI_SETID

NUMBER

9i后已经废弃字段

SET_COUNT

NUMBER

9i后已经废弃字段

·        v$buffer_pool_statistics

V$BUFFER_POOL_STATISTICS视图记录了所有缓冲池的统计数据。它的结构如下:

字段

数据类型

描述

ID

NUMBER

缓冲池ID,和上面视图描述相同。

NAME

VARCHAR2(20)

缓冲池名称

SET_MSIZE

NUMBER

缓冲池中缓存块的最大数

CNUM_REPL

NUMBER

在置换列表中的缓存块数

CNUM_WRITE

NUMBER

在写列表中的缓存块数

CNUM_SET

NUMBER

当前的缓存块数

BUF_GOT

NUMBER

读取过的缓存块数

SUM_WRITE

NUMBER

被写过的缓存块数

SUM_SCAN

NUMBER

被扫描过的缓存块数

FREE_BUFFER_WAIT

NUMBER

等待空闲块统计数

WRITE_COMPLETE_WAIT

NUMBER

等待完成写统计数

BUFFER_BUSY_WAIT

NUMBER

忙(正在被使用)等待统计数

FREE_BUFFER_INSPECTED

NUMBER

确认了的空闲缓存块数(即可用的)

DIRTY_BUFFERS_INSPECTED

NUMBER

确认了的脏缓存块数

DB_BLOCK_CHANGE

NUMBER

被修改过的数据块数

DB_BLOCK_GETS

NUMBER

读取过的数据块数

CONSISTENT_GETS

NUMBER

一致性读统计数

PHYSICAL_READS

NUMBER

物理读统计数

PHYSICAL_WRITES

NUMBER

物理写统计数

查看当前的Buffer Cache命中率:

SQL> select 1-(physical_reads)/(consistent_gets+db_block_gets)
  2  from v$buffer_pool_statistics;
 
1-(PHYSICAL_READS)/(CONSISTENT
------------------------------
             0.967658520581074
 
SQL>
·        v$bh

这一视图在深入定位缓冲区问题时很有用。它记录了缓冲区中所有数据块对象。粒度非常细。这个视图最初的目的是用于OPS(Oracle Parallel Server Oracle平行服务器,9i后称为RAC)的,是用于保证RAC中各个节点的数据一致性的。但是,我们可以通过它来查询Buffer Cache的使用情况,找出大量消耗Buffer Cache的对象。下面的语句就可以完成这一工作:

SQL> column c0 heading 'Owner'                     format a15
SQL> column c1 heading 'Object|Name'               format a30
SQL> column c2 heading 'Number|of|Buffers'         format 999,999
SQL> column c3 heading 'Percentage|ofData|Buffer' format 999,999,999
SQL> select
  2     owner                        c0,
  3     object_name                  c1,
  4     count(1)                     c2,
  5     (count(1)/(select count(*) from v$bh)) *100  c3
  6  from
  7     dba_objects o,
  8     v$bh        bh
  9  where
 10     o.object_id  = bh.objd
 11  and
 12     o.owner not in ('SYS','SYSTEM')
 13  group by
 14     owner,
 15     object_name
 16  order by
 17     count(1) desc
 18  ;
 
C0              C1                                     C2         C3
--------------- ------------------------------ ---------- ----------
PLSQLDEV        STANDARD_CITY                  17290      72.5860621
DBOWNER         MSG_LOG                        2          0.00839630
DBOWNER         COUNTRY_PK                     1          0.00419815
DBOWNER         PARAMETER                      1          0.00419815
DBOWNER         PARAMETER_PK                   1          0.00419815
DBOWNER         MSG_LOG_IDX1                   1          0.00419815
 
6 rows selected
 
SQL>

 

更重要的是,这个视图记录的粒度非常细,一条记录对应了一个数据块。这对于我们做内存问题分析或分析Oracle行为时很有帮助。

下面是这个视图的结构:

字段

数据类型

说明

FILE#

NUMBER

缓存块对应的数据块所在的数据文件号。可以通过视图DBA_DATA_FILES或V$DBFILES查询

BLOCK#

NUMBER

缓存块对应的数据块编号

CLASS#

NUMBER

分类编号

STATUS

VARCHAR2(1)

缓存块的状态

FREE:空闲,没有被使用

XCUR:排斥(正在被使用)

SCUR:可被共享

CR:一致性读

READ:正在从磁盘读入

MREC:处于从存储介质恢复状态

IREC:处于实例恢复状态

XNC

NUMBER

缓存块上由于和其他实例争用导致的PCM(Parallel Cache Management并行缓存管理)x to null锁的数量。这一字段已经被废弃。

LOCK_ELEMENT_ADDR

RAW(4 | 8)

缓存块上PCM锁的地址。如果多个缓存块的PCM锁地址相同,说明他们被同一锁锁住。

LOCK_ELEMENT_NAME

NUMBER

缓存块上PCM锁的地址。如果多个缓存块的PCM锁地址相同,说明他们被同一锁锁住。

LOCK_ELEMENT_CLASS

NUMBER

缓存块上PCM锁的地址。如果多个缓存块的PCM锁地址相同,说明他们被同一锁锁住。

FORCED_READS

NUMBER

由于其他实例的PCM锁锁住了该缓存块,导致当前实例尝试重新请求读该缓冲块的次数。

FORCED_WRITES

NUMBER

由于其他实例的PCM锁锁住了该缓存块,导致当前实例尝试重新请求写该缓冲块的次数。

DIRTY

VARCHAR2(1)

脏标志:Y – 块被修改过,是脏块;N – 不是脏块

TEMP

VARCHAR2(1)

是否为临时块:Y – 是;N – 否。

PING

VARCHAR2(1)

是否被ping住:Y – 是;N – 否。

STALE

VARCHAR2(1)

是否是陈旧块:Y – 是;N – 否。

DIRECT

VARCHAR2(1)

是否为直接读写块:Y – 是;N – 否。

NEW

VARCHAR2(1)

字段被废弃,始终为N

OBJD

NUMBER

数据块所属对象的对象标号,可以查询dba_objects

TS#

NUMBER

数据块所在的表空间号,可以查询v$tablespaces

1.1.4.   共享池(Shared pool)

SGA中的共享池由库缓存(Library Cache)、字典缓存(Dictionary Cache)、用于并行执行消息的缓冲以及控制结构组成。

Shared Pool的大小由参数SHARED_POOL_SIZE决定。在32位系统中,这个参数的默认值是8M,而64位系统中的默认值位64M。最大为4G。

对于Shared Pool的内存管理,是通过修正过的LRU算法表来实现的。

下面分别介绍Shared Pool的几个组成部分。

1.1.4.1.            库缓存(Library Cache)

Library Cache中包括共享SQL区(Shared SQL Areas)、PL/SQL存储过程和包以及控制结构(如锁、库缓存句柄)。

任何用户都可以访问共享SQL区(可以通过v$sqlarea访问,随后会介绍这个重要视图)。因此库缓存存在于SGA的共享池中。

·        共享SQL区和私有SQL区

Oracle会为每一条SQL语句运行(每运行一条语句Oracle都会打开一个游标)提供一个共享SQL区(Shared SQL Areas)和私有SQL区(Private SQL Areas属于PGA)。当发现两个(或多个)用户都在运行同一SQL语句时,Oracle会重新组织SQL区,使这些用户能重用共享SQL区。但他们还会在私有SQL区中保存一份这条SQL语句的拷贝。

一个共享SQL区中保存了一条语句的解析树和查询计划。在多用户系统中,Oracle通过为SQL语句使用同一共享SQL区多次运行来节省内存。

当一条新的SQL语句被解析时,Oracle从共享池中分配一块内存来存储共享SQL区。这块内存的大小与这条语句的复杂性相关。如果Shared Pool不够空间分配给共享SQL区,Oracle将释放从LRU链表中查找到最近最少使用的内存块,直到有足够空间给新的语句的共享SQL区。如果Oracle释放的是一个共享SQL区的内存,那么相应的语句在下次执行时需要再次解析并重新分配共享SQL区。而从解析语句到分配共享SQL区是一个比较消耗CPU的工程。这就是为什么我们提倡使用绑定变量的原因了。在没有使用绑定变量时,语句中的变量的数值不同,oracle就视为一条新的语句(9i后可以通过cursor_sharing来控制),重复上面的解析、内存分配的动作,将大大消耗系统资源,降低系统性能。

·        PL/SQL程序单元

Oracle对于PL/SQL程序单元(存储过程、函数、包、匿名PL/SQL块和触发器)的处理过程和对单个的SQL语句的处理过程相似。它会分配一个共享区来存储被解析、编译过的程序单元。同时分配一个私有区域来存放运行程序单元的会话所指定的程序单元的参数值(包括本地变量、全局变量和包变量——这也叫做包的实例化)和用于执行程序所需的内存。如果多个用户运行同一个程序单元,则他们共享同一个共享区域,并且各自保持一份私有区域,用于用户会话中指定的变量值。

而一个PL/SQL程序单元中的每条单个SQL语句的处理过程则和上面描述的SQL语句的处理过程相同。要注意一点,尽管这些语句是从PL/SQL程序单元中来的,但是Oracle还是会为这些语句分配一块共享SQL区,同时为每个用户分配一个相应的私有SQL区。

转载自:http://www.hellodba.com/reader.php?ID=102&lang=CN

你可能感兴趣的:(Oracle内存全面分析(3))