oracle实例的内存(SGA和PGA)调整,优化之原理和方法

一、SGA与PGA的结构:

SGA
查看SGA:
Sqlp> show sga
或 select * from v$sga;
Total System Global Area  289406976 bytes
Fixed Size                  1248600 bytes
Variable Size             176161448 bytes
Database Buffers          109051904 bytes
Redo Buffers                2945024 bytes

Fixed Size:包括了数据库与实例的控制信息、状态信息、字典信息等,启动时就被固定在SGA中,不会改变。
Variable Size:包括了shard pool、large pool、java pool、stream pool、游标区和其他结构
Database Buffers:数据库中数据块缓冲的地方,是SGA中最大的地方,决定数据库性能
Redo Buffers:提供REDO缓冲的地方,在OLAP中不需要太大

V$sgastat记录了SGA的一些统计信息
V$sga_dynamic_components 保存SGA中可以手动调整的区域的一些调整记录

Shard pool:
Shard_pool_size决定其大小,10g以后 自动管理
Shard_pool中数据字典和控制区结构用户无法直接控制,与用户有关的只有sql缓冲区(library cache)。
将 经常访问的过程或包用DBMS_SHARED_POOL.KEEP存储过程将该包pin在共享池中。
手工清除共享池的内容:alter system flush shard_pool;

共享池相关的几个常用的视图:
V$sqlarea 记录了所有sql的统计信息,包括执行次数、物理读、逻辑读、耗费时间等
V$sqltext_with_newline 完全显示sql语句,通过hash_value来标示语句,piece排序
V$sql_plan保存了sql的执行计划,通过工具查看
V$shared_pool_advice 对共享池的预测,可以做调整SGA的参考
SGA:System Global Area是Oracle Instance的基本组成部分,在实例启动时分配;
     系统全局域SGA主要由三部分构成:共享池、数据缓冲区、日志缓冲区。

(1)共享池:Shared Pool用于缓存最近被执行的SQL语句和最近被使用的数据定义,
        主要包括:Library cache(共享SQL区)和Data dictionary cache(数据
         字典缓冲区).共享SQL区是存放用户SQL命令的区域,数据字典缓冲区存
         放数据库运行的动态信息.不管Oracle是32 bit 还是 64 bit 的,假定应用存在没有很好的使用绑定变量的情况,也不能设置 shared_pool_size 过大,通常应该控制在100M--200M,除非是 ORACLE ERP 一类的使用了很多存储过程函数、包 ,这样的很大的系统,可以考虑增大shared_pool_size,但是如果超过500M可能是危险的,达到1G几乎就会造成CPU的严重负担,系统甚至瘫痪。所以shared_pool_size 如果超过200M还命中率不高,那么应该从应用上找原因而不是一味的增加内存,shared_pool_size 过大主要增加了管理负担和latch 的开销。
 
(2) 缓冲区高速缓存:Database Buffer Cache用于缓存从数据文件中检索出来的数据
 块,可以大大提高查询和更新数据的性能,通常可以尽可能的大。
Oracle把从data buffer中获得的数据库叫cache hit,把从磁盘获得的脚cache miss
数据缓冲 区中的数据块通过脏列表(dirty list)和LRU列表(LRU list)来管理。
 Data buffer可细分为:default pool、keep pool、recycle pool对应的参数为db_cache_size、 db_keep_cache_size 、db_recycle_size分别表示缓冲区大小
 从9i开始oracle支持不同块大小的 表空间,相应的可以为不同块大小的表空间指定不同块大小的数据缓冲区,不同块大小的数据缓冲区可以用相应的db_nk_cache_size来指定,其中 n可以是2、4、6、16或32
 V$db_cache_advice 对数据缓冲区的预测,可以做调整data buffer的参考
 V$bh、 x$bh记录了数据块在data buffer中缓冲的情况,通过这个视图可以找系统中的热点块。通过下面语句找系统中top 10 热点快所在的热点对象:

Select /*+ rule*/ owner,object_name from dba_objects
Where data_object_id in
(select obj from
(select obj from x$bh order by tch desc)
Where rownum<11);

(3)大型池:Large Pool是SGA中一个可选的内存区域,它只用于shared server环境
 
(4)Java池:ava Pool为Java命令的语法分析提供服务

PGA:Program Global Area是为每个连接到Oracle database的用户进程保留的内存。用来保存于用户进程相 关的内存段。


自动内存管理:

 从9i开始使用PGA自动管理,pga_aggregate_target参数指定session一共使用的最大PGA内存的上限。 Workarea_size_policy参数用于开关PGA内存自动管理功能,auto/manual.在OLTP环境中,自动PGA 管理只要设置到一定的值,如2G左右就能满足系统的要求。
 sql>Alter system set pga_aggregate_target=1000m scope=both;
 
  从9i开始,sga_max_size参数设置SGA 的内存大小,不能动态修改
从10g开始,指定了sga_target参数后,所有的SGA组件如:shared pool、 data buffer、 large pool都不用手工指定了,Oracle会自动管理。这一特性就是自动共享内存管理ASMM。如果设置了sga_target=0,就自动关闭自动共享内 存管理功能。Sga_target大小不能超过sga_max_size的大小。
 
 在Oracle 10g中引入了自动SGA内存管理特性,DBA可以设定SGA_TARGET告诉Oracle可用的SGA内存为多大,由Oracle根据系统负载来动态调整各组件大小,相应的数定会保存在控制文件中,使数据库重启后也记得各组件大小。

需要注意一下几点:
要使用自动SGA内存管理,STATISTICS_LEVEL参数必须设为TYPICAL或ALL,系统自动收集相应的信息用来动态调整SGA设定。

可以设定某个组件的值,Oracle SGA使用此值为该组件的最小大小
可动态调整的参数:
DB_CACHE_SIZE,SHARED_POOL_SIZE,LARGE_POOL_SIZE,JAVA_POOL_SIZE。

需手动设置的参数:
LOG_BUFFER,STREAMS_POOL,DB_NK_CACHE_SIZE,DB_KEEP_CACHE_SIZE,DB_RECYCLE_CACHE_SIZE。

手动管理SGA:

alter system set sga_max_size=1600M  scope=spfile;需重启数据库生效
Alter system set sga_target=2000m;
Alter system set db_cache_size=1000m;
Alter system set shared_pool=200m;
Alter system set sga_target=0---------关闭自动共享内存管理ASMM

11G以后sga+pga整个内存可以自动管理AMM,相关 参数memory_max_target  memory_target.设置好这两个参数后就不用关心SGA和PGA了

Alter system set memory_target=3000m SCOPE=SPFILE;
Alter system set memory_max_target=4000M SCOPE=SPFILE;  
ALTER SYSTEM SET PGA_AGGREGATE_TARGET=0 SCOPE=SPFILE;
ALTER SYSTEM SET SGA_TARGET=0 SCOPE=SPFILE;

11g手动内存管理:
Alter system set memory_target=3000m;
Alter system set sga_target=2000m;
Alter system set pga_aggregate_target=1000m;
Alter system set memory_target=0;---------关闭自动内存管理AMM

二、分析与调整:

1、系统全局域:
SGA与操作系统、内存大小、cpu、同时登录的用户数有关。可占OS系统物理内存的1/2到1/3,当然,如果服务器上只有oracle的话,可以分配的更大一些,如果还有其他服务,如IIS等,那就要分的小一些。
  
  1、共享池:
  修改共享池的大小,ALTER SYSTEM SET SHARED_POOL_SIZE = 64M;
  查看共享SQL区的使用率: 
select(sum(pins-reloads))/sum(pins) "Library cache" from v$librarycache;
这个使用率应该在90%以上,否则需要增加共享池的大小。
  查看数据字典缓冲区的使用率:
select (sum(gets-getmisses-usage-fixed))/sum(gets) "Data dictionary cache" from v$rowcache;
这个使用率也应该在90%以上,否则需要增加共享池的大小。
  
   2、缓冲区高速缓存:它的大小要根据数据量来决定,在OLTP系统中要求data buffer 的命中率在95%以上.
SGA=((db_block_buffers * block size+shared_pool_size+large_pool_size+java_pool_size+log_buffers)+1MB
查看数据库数据缓冲区的使用情况:

 SELECT name,value FROM v$sysstat order by name WHERE name IN(''DB BLOCK GETS'',''CONSISTENT GETS'',''PHYSICAL READS''); 
 计算出来数据缓冲区的使用命中率=1-(physical reads/(db block gets+consistent gets)),这个命中率应该在90%以上,否则需要增加数据缓冲区的大小。
SQL>select sum(pins) "请求存取数",sum(reloads) "不命中数",sum(reloads)/sum(pins) from v$librarycache  
  其中,pins,显示在库高速缓存中执行的次数;reload,显示在执行阶段库高速缓存不命中的数目,一般 sum(reloads)/sum(pins)的值应接近于零.如果大于1%就应该增加shared_pool_size的值, 来提高数据字典高速缓存可用的内存数量,减少不命中数.
  通过动态性能表v$rowcache来查询数据字典高速缓存的活动:  
select sum(gets) "请求存取数",sum(getmisses) "不命中数" from v$rowcache;   
 其中,gets,显示请求相应项的总数; getmisses,显示造成高速缓存不命中的数据请求数.   
 Hit ratio与wait events:
SQL>select value from $pgastat where name =''cache hit percentage'';
 Hit ratio与wait events是此消彼涨,在执行类似于
SQL>select col1,col2,.. from tab1 a where exists (select 1 from tab2 where a.col3 = b.col3) where ....
 的语句的时候,如果tab1的记录很多的话,你会发现系统的hit ratio会有很大的提高,wait events是否会改观呢.

   3、日志缓冲区
  SELECT name, value  FROM v$sysstat WHERE name IN (''redo entries'',''redo log space requests'')
查看日志缓冲区的使用情况。
查询出的结果可以计算出日志缓冲区的申请失败率:     
 申请失败率=requests/entries,申请失败率应该接近于0,否则说明日志缓冲区开设太小,需要增加ORACLE数据库的日志缓冲区。

   4、大型池:
可以减轻共享池的负担;可以为备份、恢复等操作来使用;不使用LRU算法来管理
其大小由数据库的‘共享模式/db模式’如果是共享模式的话,要分配的大一些
 指定Large Pool的大小,
ALTER SYSTEM SET LARGE_POOL_SIZE=64M
  
  5、Java池:
  在安装和使用Java的情况下使用


三.如何估算PGA,SGA的大小,配置数据库服务器的内存
ORACLE给的建议是: 一个数据库服务器,分80%的内存给数据库,20%的内存给操作系统.
OLTP系统  PGA=(Total Memory)*80%*20%。余下SGA。
DSS系统 PGA=(Total Memory)*80%*70%。 余下SGA。
混合系统 PGA=(Total Memory)*80%*50%。余下SGA。
 
PGA:
SQL> select * from v$pgastat; 
NAME                                                                  VALUE UNIT
---------------------------------------------------------------- ---------- ------------
aggregate PGA target parameter                                    104857600 bytes  
-----这个值等于参数PGA_AGGREGATE_TARGET的值,如果此值为0,表示禁用了PGA自动管理。
aggregate PGA auto target                                          75220992 bytes      
-----表示PGA还能提供多少内存给自动运行模式,通常这个值接近pga_aggregate_target-total pga inuse.
global memory bound                                                20971520 bytes 
-----工作区执行的最大值,如果这个值小于1M,马上增加PGA大小
total PGA inuse                                                    30167040 bytes 
-----当前分配PGA的总大小,这个值有可能大于PGA,如果PGA设置太小.这个值接近
total PGA allocated                                                52124672 bytes 
-----工作区花费的总大小
maximum PGA allocated                                              67066880 bytes
total freeable PGA memory                                                 0 bytes         ----没有了空闲的PGA
process count                                                            23                    ----当前一个有23个process
max processes count                                                      25 
PGA memory freed back to OS                                               0 bytes
total PGA used for auto workareas                                   8891392 bytes
maximum PGA used for auto workareas                                22263808 bytes
total PGA used for manual workareas                                       0 bytes                  ---为0自动管理
maximum PGA used for manual workareas                                     0 bytes            ---为0自动管理
over allocation count                                                     0        
如果PGA设置太小,导致PGA有时大于PGA_AGGREGATE_TARGET的值,此处为0,说明PGA没有扩展大于TARGET的值,如 果此值出现过,那么增加PGA大小。
bytes processed                                                   124434432 bytes
extra bytes read/written                                                  0 bytes
cache hit percentage                                                    100 percent  ---命中率为100%,如果太小增加PGA 
recompute count (total)                                                6651 
19 rows selected

SQL> select max(pga_used_mem)/1024/1024 M from v$process;   ----当前一个process消耗最大的内存 
M
----------
9.12815189 
SQL> select min(pga_used_mem)/1024/1024 M from v$process where pga_used_mem>0; ---process消耗最少内存 
M
----------
0.19186878 
SQL> select max(pga_used_mem)/1024/1024 M from v$process ;    ----process曾经消耗的最大内存 
M
----------
9.12815189 
SQL> select sum(pga_used_mem)/1024/1024 from v$process;   ----当前process一共消耗的PGA 
SUM(PGA_USED_MEM)/1024/1024
---------------------------
28.8192501068115

如何设置PGA呢?我们可以在压力测试阶段,模拟一下系统的运行,然后运行 
select (select sum(pga_used_mem)/1024/1024 from v$process) /(select count(*) from v$process) from dual;
得到一个process大约占用了多少的内存,然后估算系统一共会有多少连接,比如一共有500个连接, 
如果processes=450,那么Sessions=1.1*process +5=500,,再乘以一个process需要消耗的内存,就能大约估算出PGA需要设置多大。 
最好将PGA设置的值比计算出的值大一点,PGA值设定好后,就可以根据系统的性质,如果系统为OLTP,那么总的内存可以设置为 PGA/0.16,最后也能估算出SGA的大小

下面摘抄eygle的关于一个process能够分配的最大内存(串行操作)的规则: 
10gR1之前,对于串行操作(非并行)一个process能够分配的最大的内存为 min(5%pga_aggregate_target,100m) 
10gR2之后,对于串行操作(非并行)一个process能够分配的最大内存有如下规则: 
如果pga_aggregate_target<=500m,那么最大的内存为20%*pga_aggregate_target. 
如果500m 如果1000m 如果pga_aggregate_target>2.5G,那么最大内存为2.5G.
就是在非并行方式下,“期望尺寸”为min(5%*pga_aggregate_target,50%*_pga_max_size,_smm_max_size).

SQL>select ksppinm, ksppstvl, ksppdesc from x$ksppi x, x$ksppcv y where x.indx = y.indx and ksppinm in ('_pga_max_size','_smm_max_size');
SQL> 
NAME                                                                             VALUE                                                                            DESCRIB
-------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
_smm_max_size (kbyte)                                                                   20480                                                                            maximum work area size in auto mode (serial)

SQL> show parameter pga
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target                 big integer 100M

此处一个process能够分配的最大内存为20M,因为我的PGA=100M,符合上面的规则。
隐含参数_smm_max_size表示一个process能够分配最大的memory.


SGA:
1、Shared pool tunning
Shared pool的优化应该放在优先考虑,因为一个cache miss在shared pool中发生比在data buffer中发生导致的成本更高,由于dictionary数据一般比library cache中的数据在内存中保存的时间长,所以关键是library cache的优化。
Gets:(parse)在namespace中查找对象的次数;
Pins:(execution)在namespace中读取或执行对象的次数;
Reloads:(reparse)在执行阶段library cache misses的次数,导致sql需要重新解析。

1) 检查v$librarycache中sql area的gethitratio是否超过90%,如果未超过90%,应该检查应用代码,提高应用代码的效率。
Select gethitratio from v$librarycache where namespace='SQL AREA';

2) v$librarycache中reloads/pins的比率应该小于1%,如果大于1%,应该增加参数shared_pool_size的值。
Select sum(pins) executions,sum(reloads) cache_misses,sum(reloads)/sum(pins) from v$librarycache;
reloads/pins>1%有两种可能,一种是library cache空间不足,一种是sql中引用的对象不合法。

3)shared pool reserved size一般是shared pool size的10%,不能超过50%。V$shared_pool_reserved中的request misses=0或没有持续增长,或者free_memory大于shared pool reserved size的50%,表明shared pool reserved size过大,可以压缩。

4)将大的匿名pl/sql代码块转换成小的匿名pl/sql代码块调用存储过程。

5)从9i开始,可以将execution plan与sql语句一起保存在library cache中,方便进行性能诊断。从v$sql_plan中可以看到execution plans。

6)保留大的对象在shared pool中。大的对象是造成内存碎片的主要原因,为了腾出空间许多小对象需要移出内存,从而影响了用户的性能。因此需要将一些常用的大的对象保留在shared pool中,下列对象需要保留在shared pool中:
a. 经常使用的存储过程;
b. 经常操作的表上的已编译的触发器
c. Sequence,因为Sequence移出shared pool后可能产生号码丢失。
查找没有保存在library cache中的大对象:
Select * from v$db_object_cache where sharable_mem>10000 and type in ('PACKAGE','PROCEDURE','FUNCTION','PACKAGE BODY') and kept='NO';
将这些对象保存在library cache中:
Execute dbms_shared_pool.keep(‘package_name’);
对应脚本:dbmspool.sql

7)查找是否存在过大的匿名pl/sql代码块。两种解决方案:
A.转换成小的匿名块调用存储过程
B.将其保留在shared pool中
查找是否存在过大的匿名pl/sql块:
Select sql_text from v$sqlarea where command_type=47 and length(sql_text)>500;

8)Dictionary cache的 优化 
避免出现Dictionary cache的misses,或者misses的数量保持稳定,只能通过调整shared_pool_size来间接调整dictionary cache的大小。
Percent misses应该很低:大部分应该低于2%,合计应该低于15%
Select sum(getmisses)/sum(gets) from v$rowcache;
若超过15%,增加shared_pool_size的值。


2、Buffer Cache

1)granule大小的设置,db_cache_size以字节为单位定义了default buffer pool的大小。
如果SGA<128M,granule=4M,否则granule=16M,即需要调整sga的时候以granule为单位增加大小,并且sga的大小应该是granule的整数倍。

2) 根据v$db_cache_advice调整buffer cache的大小
SELECT size_for_estimate,buffers_for_estimate,estd_physical_read_factor,estd_physical_reads FROM v$db_cache_advice WHERE NAME='DEFAULT' AND advice_status='ON' AND block_size=(SELECT Value FROM v$parameter WHERE NAME='db_block_size');
estd_physical_read_factor<=1

3) 统计buffer cache的cache hit ratio>90%,如果低于90%,可以用下列方案解决:
增加buffer cache的值;
使用多个buffer pool;
Cache table;
为 sorting and parallel reads 建独立的buffer cache;
SELECT NAME,value FROM v$sysstat WHERE NAME IN ('session logical reads','physical reads','physical reads direct','physical reads direct(lob)');
Cache hit ratio=1-(physical reads-physical reads direct-physical reads direct (lob))/session logical reads;
Select 1-(phy.value-dir.value-lob.value)/log.value from v$sysstat log, v$sysstat phy, v$sysstat dir, v$sysstat LOB where log.name='session logical reads' and phy.name='physical reads' and dir.name='physical reads direct' and lob.name='physical reads direct (lob)';
影响cache hit ratio的因素:
全表扫描;应用设计;大表的随机访问;cache hits的不均衡分布

4)表空间使用自动空间管理,消除了自由空间列表的需求,可以减少数据库的竞争

3、其他SGA对象
1)redo log buffer
对应的参数是log_buffer,缺省值与 OS相关,一般是500K。检查v$session_wait中是否存在log buffer wait,v$sysstat中是否存在redo buffer allocation retries
A、检查是否存在log buffer wait:
Select * from v$session_wait where event='log buffer wait';
如果出现等待,一是可以增加log buffer的大小,也可以通过将log 文件移到访问速度更快的磁盘来解决。
B、Select name,value from v$sysstat where name in (‘redo buffer allocation retries’,’redo entries’)
Redo buffer allocation retries接近0,小于redo entries 的1%,如果一直在增长,表明进程已经不得不等待redo buffer的空间。如果Redo buffer allocation retries过大,增加log_buffer的值。
C、检查日志文件上是否存在磁盘IO竞争现象
Select event,total_waits,time_waited,average_wait from v$system_event where event like ‘log file switch completion%’;
如果存在竞争,可以考虑将log文件转移到独立的、更快的存储设备上或增大log文件。
D、检查点的设置是否合理
检查alert.log文件中,是否存在‘checkpoint not complete’;
Select event,total_waits,time_waited,average_wait from v$system_event where event like ‘log file switch (check%’;
如果存在等待,调整log_checkpoint_interval、log_checkpoint_timeout的设置。
E、检查log archiver的工作
Select event,total_waits,time_waited,average_wait from v$system_event where event like ‘log file switch (arch%’;
如果存在等待,检查保存归档日志的存储设备是否已满,增加日志文件组,调整log_archiver_max_processes。
F、DB_block_checksum=true,因此增加了性能负担。(为了保证数据的一致性,oracle的写数据的时候加一个checksum在block上,在读数据的时候对checksum进行验证)

2)java pool
对于大的应用,java_pool_size应>=50M,对于一般的java存储过程,缺省的20M已经够用了。

3)检查是否需要调整DBWn
Select total_waits from v$system_event where event=’free buffer waits’;

你可能感兴趣的:(Oracle,转载)