会导致排序的语句有 SELECT DISTINCT , MINUS , INTERSECT , UNION 和 min()、max()、count() 操作;而不会导致排序的语句有 UPDATE , 带BETWEEN子句的SELECT 等等。 这四个参数都是针对会话进行设置的,是单个会话使用的内存的大小,而不是整个数据库使用的。偶尔会看见有人误解了这个参数以为是整个数据库使用的大小,这是极其严重的错误。假如设置了MTS,则UGA被分配在large_pool_size,也就是说放在了共享内存里面,不同进程(线程)之间可以共享这部分内存。在这个基础上,我们假设数据库存在并发执行server process 为100 个,根据上面我们4 个参数在oracle8.1.7 下的默认值,我们来计算独立模式下PGA 的大致大小。由于会话并不会经常使用create_bitmap_area_size 、bitmap_merge_area_size,所以我们通常不对四个参数求和。在考虑到除这四个参数外会话所保存的变量、堆栈等信息,我们估计为 2M,则200 个进程最大可能使用200M 的PGA。
1.2.2 一个经验公式 现在,根据上面这些假定,我们来看SGA 实际能达到多少内存。在1G 的内存的服务器上,我们能分配给SGA 的内存大约为400—500M。若是2G 的内存,大约可以分到1G的内存给SGA,8G 的内存可以分到5G的内存给SGA。当然我们这里是以默认的排序部分内存sort_area_size=64k进行衡量的,假如我们需要调大该参数和 hash_area_size等参数,然后我们应该根据并发的进程的数量,来衡量考虑这个问题。
事实上,通常我们更习惯通过直观的公式化来表达这样的问题: OS 使用内存+SGA+并发执行进程数*(sort_area_size+hash_ara_size+2M) < 0.7*总内存
(公式是死的,系统是活的,实际应用的调整不必框公式,这不过是一个参考建议)
在我们的实际应用中,假如采用的是裸设备,我们可适当的增大SGA(如果需要的话)。由于目前几乎所有的操作系统都使用虚拟缓存,所以实际上如果就算SGA 设置的比较大也不会导致错误,而是可能出现频繁的内存页的换入与换出(page in/out)。在操作系统一级如果观察到这个现象,那么我们就需要调整内存的设置。
1.2.3 各个参数的设置 那么SGA中的各个参数具体应该按照什么样的原则来设置呢,下面进行讨论: log_buffer 对于日志缓冲区的大小设置,通常我觉得没有过多的建议,因为参考LGWR写的触发条件之后,我们会发现通常超过3M意义不是很大。作为一个正式系统,可能考虑先设置这部分为log_buffer=1—3M 大小,然后针对具体情况再调整。 large_pool_size 对于大缓冲池的设置,假如不使用MTS,建议在20—30M 足够了。这部分主要用来保存并行查询时候的一些信息,还有就是RMAN 在备份的时候可能会使用到。如果设置了MTS,则由于UGA部分要移入这里,则需要具体根据session最大数量和 sort_ares_size 等相关会话内存参数的设置来综合考虑这部分大小的设置,一般可以考虑为 session * (sort_area_size + 2M)。这里要提醒一点,不是必须使用MTS,我们都不主张使用MTS,尤其同时在线用户数小于500的情况下。。 java_pool_size 假如数据库没有使用JAVA,我们通常认为保留10—20M大小足够了。事实上可以更少,甚至最少只需要32k,但具体跟安装数据库的时候的组件相关(比如http server)。 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(特殊情况下可以更大)。
上一篇:Recordset.Open方法参数介绍
下一篇:很有用的oracle 函数
|