一、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
就是在非并行方式下,“期望尺寸”为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’;