全表扫描

        全表扫描

发生全表扫描(Full Table Scan)时,用户进程读取表的数据块, 并将他们放在LRU链表的LRU端(和上面不同,不是放在MRU端)。这样做的目的是为了使全表扫描的数据尽快被移出。因为全表扫描一般发生的频率较低,并且全表扫描的数据块大部分在以后都不会被经常使用到。
而如果你希望全表扫描的数据能被cache住,使之在扫描时放在MRU端,可以通过在创建或修改表(或簇)时,指定CACHE参数


·        多缓冲池

你可以配置不同的buffer cache,可以达到不同的cache数据的目的。比如,可以设置一部分buffer cache缓存过的数据在使用后后马上释放,使后来的数据可以立即使用缓冲池;还可以设置数据进入缓冲池后就被keep住不再释放。部分数据库对象(表、簇、索引以及分区)可以控制他们的数据缓存的行为,而这些不同的缓存行为就使用不同缓冲池。

o        保持缓冲池(Keep Buffer Pool) 用于缓存那些永久驻入内存的数据块。它的大小由参数DB_KEEP_CACHE_SZIE控制;

o        回收缓冲池(Recycle Buffer Pool)会立即清除那些不在使用的数据缓存块。它的大小由参数DB_RECYLE_CACHE_SIZE指定;

o        默认的标准缓存池,也就是上面所说的DB_CACHE_SIZE指定。

这三个参数相互之间是独立的。并且他们都只适用于标准块尺寸的数据块。与8i兼容参数DB_BLOCK_BUFFERS相应的,DB_KEEP_CACHE_SIZE对应有BUFFER_POOL_KEEP、DB_RECYLE_CACHE_SIZE对应有BUFFER_POOL_RECYCLE。同样,这些参数之间是互斥的,即DB_KEEP_CACHE_SIZE和BUFFER_POOL_KEEP之间只能设置一个。

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来控制),重复上面的解析、内存分配的动作,将大大消耗系统资源,降低系统性能。
1.1.4.5.            将重要、常用对象保持(Keep)在共享池中

前面提到,根据LRU算法,一些一段时间没有使用到的内存块会被情况释放。这就可能导致一些重要的对象(如一个含有大量通用算法函数的包、被cache的序列)被从内存中清除掉。这些对象可能只是间歇被使用,但是因为他们的处理过程复杂(不仅包本身重新分配内存、解析,还要检查里面的所有语句),要在内存中重建他们的代价非常大。

我们可以通过调用存储过程DBMS_SHARED_POOL.KEEP将这些对象保持在共享池中来降低这种风险。这个存储过程立即将对象及其从事对象载入library cache中,并将他们都标记为保持(Keeping)状态。对于这种对象,我们建议在实例启动时就Keep住,以减少内存碎片的几率。

有一种观点认为那些大对象(如包)是没有必要被Keep住的,因为他们会被保持在共享池的保留区(如前所述,这个区通常使用率很低),所以一般不可能被清出。这个观点是错误滴!因为大多数大对象实际上是被分为多个小的内存段被载入共享池的,因此根本不会因为对象的大小而受到特别的保护。

另外,也不要通过频繁调用某些对象以防止他们被从共享池中清出。如果共享池大小设置合理,在系统运行的高峰时期,LRU链表会相对较短,那些没有被pin住的对象会很快被清出,除非他们被keep住了。
1.2.            PGA (The Process Global Area)

PGA(Program Global Area程序全局区)是一块包含一个服务进程的数据和控制信息的内存区域。它是Oracle在一个服务进程启动是创建的,是非共享的。一个Oracle进程拥有一个PGA内存区。一个PGA也只能被拥有它的那个服务进程所访问,只有这个进程中的Oracle代码才能读写它。因此,PGA中的结构是不需要Latch保护的。

我们可以设置所有服务进程的PGA内存总数受到实例分配的总体PGA(Aggregated PGA)限制。

在专有服务器(Dedicated Server)模式下,Oracle会为每个会话启动一个Oracle进程;而在多线程服务(Multi-Thread Server MTS)模式下,由多个会话共享通一个Oracle服务进程。

PGA中包含了关于进程使用到的操作系统资源的信息,以及一些关于进程状态的信息。而关于进程使用的Oracle共享资源的信息则是在SGA中。这样做可以使在进程以外中止时,能够及时释放和清除这些资源。

猜你喜欢

转载自swearyd7.iteye.com/blog/1508576
今日推荐