oracle的内存可以按照共享和私有的角度分为系统全局区和进程全局区,也就是SGA和PGA(process global area or private global area)。对于SGA区域内的内存来说,是共享的全局的,在UNIX上,必须为oracle设置共享内存段(可以是一个或者多个),因为oracle在UNIX上是多进程;而在WINDOWS上oracle是单进程(多个线程),所以不用设置共享内存段。PGA是属于进程(线程)私有的区域。在oracle使用共享服务器模式下(MTS),PGA中的一部分,也就是UGA会被放入共享内存large_pool_size中。
对于SGA部分,我们通过sqlplus中查询可以看到:
SQL> select * from v$sga;
NAME VALUE
-------------------- ----------
Fixed Size 454032
Variable Size 109051904
Database Buffers 385875968
Redo Buffers 667648
shared_pool_size
这是迄今为止最具有争议的一部分内存设置。按照很多文档的描述,这部分内容应该几乎和数据缓冲区差不多大小。但实际上情况却不是这样的。首先我们要考究一个问题,那就是这部分内存的作用,它是为了缓存已经被解析过的SQL,而使其能被重用,不再解析。这样做的原因是因为,对于一个新的SQL(shared_pool里面不存在已经解析的可用的相同的SQL),数据库将执行硬解析,这是一个很消耗资源的过程。而若已经存在,则进行的仅仅是软分析(在共享池中寻找相同SQL),这样消耗的资源大大减少。所以我们期望能多共享一些SQL,并且如果该参数设置不够大,经常会出现ora-04031错误,表示为了解析新的SQL,没有可用的足够大的连续空闲空间,这样自然我们期望该参数能大一些。但是该参数的增大,却也有负面的影响,因为需要维护共享的结构,内存的增大也会使得SQL的老化的代价更高,带来大量的管理的开销,所有这些可能会导致CPU的严重问题。
在一个充分使用绑定变量的比较大的系统中,shared_pool_size的开销通常应该维持在300M以内。除非系统使用了大量的存储过程、函数、包,比如oracle erp这样的应用,可能会达到500M甚至更高。于是我们假定一个1G内存的系统,可能考虑设置该参数为100M,2G的系统考虑设置为150M,8G的系统可以考虑设置为200—300M。
对于一个没有充分使用或者没有使用绑定变量系统,这可能给我们带来一个严重的问题。所谓没有使用bind var 的SQL,我们称为Literal SQL。也就是比如这样的两句SQL我们认为是不同的SQL,需要进行2次硬解析:
select * from EMP where name = ‘TOM’;
select * from EMP where name = ‘JERRY’;
假如把’TOM’ 和 ‘JERRY’ 换做变量V,那就是使用了bind var,我们可以认为是同样的SQL从而能很好地共享。共享SQL本来就是shared_pool_size这部分内存存在的本意,oracle的目的也在于此,而我们不使用bind var就是违背了oracle的初衷,这样将给我们的系统带来严重的问题。当然,如果通过在操作系统监控,没有发现严重的cpu问题,我们如果发现该共享池命中率不高可以适当的增加shred_pool_size。但是通常我们不主张这部分内存超过800M(特殊情况下可以更大)。
事实上,可能的话我们甚至要想办法避免软分析,这在不同的程序语言中实现方式有差异。我们也可能通过设置session_cached_cursors 参数来获得帮助(这将增大PGA)。
Data buffer
现在我们来谈数据缓冲区,在确定了SGA的大小并分配完了前面部分的内存后,其余的,都分配给这部分内存。通常,在允许的情况下,我们都尝试使得这部分内存更大。这部分内存的作用主要是缓存 DB BLOCK,减少甚至避免从磁盘上获取数据,在8i中是由db_block_buffers*db_block_size来决定大小的(包含default、keep、recycle)。如果我们设置了buffer_pool_keep 和buffer_pool_recycle,这两部分内存的大小包含在前面设置中(db_block_buffers*db_block_size)。
buffer_pool_keep 是用来取代8i版本以前的缓存频繁小表于LUR 的MOST USED端的。通过开辟一段独立的内存用于缓存频繁的小表,在创建表的时候可以指定存储参数,或者也可以动态修改表的存储参数(alter table t storage(buffer_pool keep);)。
Buffer_pool_recycle 作为一块单独开辟出来的内存,主要用于很少执行的大表全表扫描的查询,使得这些大表扫描不会影响到default里面LRU而冲击整个数据库缓冲区的性能。虽然这样有可能降低大表的全表扫描的性能,但是保护了整体性能不间歇性的受到较大的冲击。同样,除了设置参数外还需要在创建表的过程中使用存储参数或者动态修改表的存储参数(alter table t storage(buffer_pool recycle);)
Data buffer
9i中保留了8i中的参数,如设置了新的参数,则忽略旧的参数。9i中用db_cache_size来取代db_block_buffers,用db_keep_cache_size取代buffer_pool_keep,用db_recycle_cache_size取代buffer_pool_recycle;这里要注意9i中设置的是实际的缓存大小而不再是块的数量。另外9i新增加了db_nk_cache_size,这是为了支持在同一个数据库中使用不同的块大小而设置的。对于不同的表空间,可以定义不同的数据块的大小,而缓冲区的定义则依靠该参数的支持。其中n可以为2、4、6、8、16等不同的值。在这里顺便提及的一个参数就是db_block_lru_latches,该参数在9i中已经成为了保留参数,不推荐手工设置。
SQL> select sum(pinhits)/sum(pins)*100 "hit radio" from v$librarycache;
hit radio
----------
99.809291
假如共享池的命中率低于95%,就要考虑调整应用(通常是没使用bind var )或者增加内存
关于排序部分
SQL> select name,value from v$sysstat where name like '%sort%';
NAME VALUE
---------------------------------------------------------------- ----------
sorts (memory) 67935
sorts (disk) 1
sorts (rows) 7070
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
PL/SQL Release 8.1.7.0.0 - Production
CORE 8.1.7.0.0 Production
TNS for 32-bit Windows: Version 8.1.7.0.0 - Production
NLSRTL Version 3.4.1.0.0 - Production
但是在特定的操作系统下,可能提供了一定的手段,使得我们可以使用超过1.7G的内存,达到2G以上甚至更多。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/pharaohsprince/archive/2005/07/07/416220.aspx