【IT168 技术文档】
调整操作系统的内存需求
减少页的换入换出;
将SGA置于主存之中
使用SGA的主要目的是为了在内存中存储数据,以利于快速访问。通过设置初始化参数PRE_PAGE_SGA=YES,在数据库启动时,可以将整个SGA读入内存,这样会减少在启动后ORACLE达到全部性能的总的时间。
使用如下命令可以查看SGA所分配的内存以及其内部的结构:
SVRMGR> SHOW SGA
Total System Global Area 107720688 bytes
Fixed Size 69616 bytes
Variable Size 90701824 bytes
Database Buffers 16777216 bytes
Redo Buffers 172032 bytes
为单个用户分配足够的内存
调整redo log缓冲区
参数LOG_BUFFER指定了REDO LOG的缓冲区的保留大小。LOG写进程(LGWR)在该缓冲区被填充时总是运行的,在新的LOG进入缓冲区时,原来的LOG应已经写入磁盘。
调整私有sql和pl/sql区
标识不必要的语法分析调用
1. 在sql跟踪工具有效时运行应用
2. 查看视图V$SQLAREA view
SVRMGR> select sql_text,parse_calls,executions from v$sqlarea ;
如果parse_calls值接近execution值,可能就是不断地对sql语句进行语法分析
3. 执行如下查询:
select *from v$statname where name in (‘parse_count(hard)’,’execute_count’);
其结果类似于:
statistic#, name
----------------------------------
100 parse_count
90 execute_count
然后执行如下查询:
select * from v$sesstat where statistics# in(90,100) order by value , sid ;
减少不必要的语法分析调用
初始化参数open_cursors的最大值依赖于操作系统,最少值为5
调整共享池
数据字典或库快存的没有命中,其开销大大多于缓冲快存的没有命中,因此,首先应该为共享池分配足够的空间。
使用如下语句可以确定库快存和数据字典快存的命中率:
select(sum(pins-reloads))/sum(pins)“Lib Cache”from v$librarycache ;
select (sum(gets-getmisses-usage-fixed))/sum(gets)“Row Cache”from v$librarycache;
共享池中的自由内存可以查看:
select * from v$sgastat where name=’free memory’;
当然,如果共享池满了并不一定存在问题,只要上面所说的比率接近于1,就不需要增加共享池大小;
如果自由内存接近于0而且库快存或数据字典快存的命中率小于0.95,那么需要增加共享池的大小。
调整Library Cache
1. 检查库快存的活动
select sum(pins) “Executions”,sum(reloads)”Cache Misses while Executing” from v$librarycache ;
“Executions”列指明sql语句,pl/sql块和实体定义被访问执行了的次数,”Cache Misses while Executing”指明其中没有命中的次数。
2. 减少库快存的非命中
1、 分配更多的库快存(可以增加初始化参数shared pool size的值;为了利用增加的共享sql区,增加初始化参数open cursors的值);
2、 尽可能使用标准的sql语句(sql语句或pl/sql块必须一致,包括字符和空格;sql语句或pl/sql块中对schema实体的引用必须解析到同一schema的同一对象;sql语句中试用的变量的名字和数据类型必须匹配;sql语句必须使用相同的优化方法和优化目标);
尽可能使用标准的sql语句,策略:
语句中尽量使用变量而不要使用常量
确保应用用户不会改变优化方法和目标
标准化的变量命名和空格转换
尽可能使用存储过程
3、 使用cursor_space_for_time加速共享sql区的访问:该参数指定是否共享sql区可以释放,如果为false(默认值),一个共享sql区就可以被释放;如果为true,一个共享的sql区只存在所有与其相关的游标关闭后才可以被释放。
如果库快存在语句执行时有非命中,不要将其设置为true,否则对新的sql语句将没有空间。
调整Data Dictionary Cache
1、 监视数据字典快存的活动
select sum(gets) “Data Dictionary Gets”, sum(getmisses) “Data Dictionary Cache Get Misses” from v$rowcache ;
2、 减少数据字典快存的非命中
对频繁访问的数据字典快存没命中和命中比应少于10%-15%。
要增加数据字典快存可用的内存数,需要增加初始参数shared_pool_size的值。
调整多线程服务器的共享池
查询动态表v$sesstat可以确定会话信息的大小:
select sum(value)||‘bytes’”Total memory for all sessions” from v$sesstat, v$statname where name=’session uga memort’ and v$sesstat statistic#=v$statname.statistic#;
显示信息如下:
Total memory for all sessions
--------------------------------------
157125 bytes
结果指明当前分配给所有会话的内存。
调整共享池的保留空间
shared_pool_reserved_size为大的存储保留的shared_pool_size总量;
shared_pool_reserved_min_alloc-控制保留内存的分配;
要创建一个保留列表,shared_pool_reserved_size必须大于shared_pool_reserved_min_alloc。
优化共享池:
用以下语句检测命中率:
select sum(pins)"pinned",sum(reloads)"reloaded" from v$librarycache
pinned reloaded
---------- ---------
2474 17
命中率=pinned/ reloaded
若命中率低可增大INIT.ORA中SHARED_POOL_SIZE的值。
调整快速缓存
利用缓存的命中率评价快速缓存的活动
select name,value from v$sysstat where name in (‘db block gets’,’consistent_gets’,’physical reads‘);
db block gets, consistent_gets其和为数据请求总数,physical reads为数据请求导致访问磁盘数据文件的总数。
增加db_block_buffers应该遵循如下规则:
缓存命中率低于0.9;
前面增加的db_block_buffers有效
提高缓冲区命中率
如果缓冲命中率低,如小于60%或70%,那么需要增加缓冲区中的缓存数。方法是增大db_block_buffers的值。
表v$recent_bucket的每一行反映在缓存中增加一个缓冲区的相应性能值,其中rownum列比可能增加到缓存的缓冲区数小1;count列通过增加缓冲区数rownum+1到缓存,增加的缓冲区命中。
查询v$recent_bucket视图:select sum(count) ach from v$recent_bucket where rownum<20 ;
使用如下公式计算命中率(ACH为增加的命中次数):Hit Ratio=1-(physical reads-ACH/(db block gets+consistent gets) );
组合v$recent_bucket视图中的行,使用如下语句:select 250*TRUNC(ROWNUM/250)+1||’to’||250*(TRUNC(ROWNUM/250)+1) “Interval”,sum(count)”Buffer Cache Hits” from v$recent_bucket group by trunc(ROWNUM/250) ;
在命中率高时,删除不必要的缓存
减少参数DB_BLOCK_BUFFERS的值可以使缓存变小,(最小值为4)。
视图v$CURRENT_BUCKET包含对一个小缓存的性能统计,其列描述如下:
ROWNUM—缓存中可能的缓冲区数
COUNT—对缓冲区数ROWNUM的缓存命中数
初始参数DB_BLOCK_LRU_STATISTICS控制视图V$CURRENT_BUCKET的统计,默认值为FALSE,意味着不收集统计数据。将其设置为TRUE,视图V$CURRENT_BUCKET将收集统计。
查询V$CURRENT_BUCKET视图,如果当前缓存为100,如果想知道在90时,缓存非命中的增加数,使用如下语句:
SELECT SUM(COUNT) ACM FROM V$CURRENT_BUCKET WHERE ROWNUM>=90 ;
计算命中率(ACM为增加的非命中次数):Hit Ratio=1-(physical reads + ACM/(db block gets+consistent gets));
也可以将100个缓冲区分为4个25个缓冲区段:
select 25*TRUNC(ROWNUM/25)+1||’to’||25*(TRUNC(ROWNUM/25+1)”Interval”,sum(count)”Buffer Cache Hits” from v$CURRENT_BUCKET where rownum>0 group by TRUNC(ROWNUM/25));
其中INTERVAL为缓冲区段,BUFFER CACHE HITS为对应段的缓存命中率。
优化数据库缓冲区高速缓存:
select name,value from v$sysstat where name in ('db block gets','consistent gets','physical reads') ;
NAME VALUE
------------------------- ---------
db block gets 3700
consistent gets 17603
physical reads 523
计算公式:
Hit Ratio = 1-(physical reads / ( db block gets + consisten gets))
若命中率低可以加大INITXXX.ORA中DB_BLOCK_BUFFER的值。
调整多缓冲池
多缓冲池特性概述
可以使用keep缓冲池来维护缓存中的实体,使用recycle缓冲池来防止实体占用缓存中不必要的空间;
可以将大的数据段置于独立的recycle缓存中,将小的数据段置于独立的keep缓存中。
何时使用多缓冲池
1. 查找oracle内部实体数据段的数目:
select data_object_id,object_type from user_objects where object_name=’
2. 查找对应该段名的缓存中的缓冲区数:
select count(*) buffers from x$bh where obj=
3. 查找实例中的缓冲区总数:
select value “total buffers ” from v$parameter where name=’db_block_buffers’ ;
4. 计算当前有指定段使用的缓存所占的比率:
%cache used by segment_name=buffers(step 2)/buffers(step 3);
使用多缓冲池调节缓存
减少I/O操作;
隔离缓存中的实体;
限制实体在缓存中的一个部分
使多缓冲池生效
定义新缓冲池:使用初始参数BUFFER_POOL_NAME来定义缓冲池,每个缓冲池可以指定两个属性:缓冲池中的缓冲区数;分配该缓冲池的LRU latches数。
用于定义缓冲池的初始参数有:
BUFFER_POOL_KEEP-定义keep缓冲池
BUFFER_POOL_RECYCLE-定义recycle缓冲池
DB_BLOCK_BUFFERS-定义数据库实例的缓冲区数
DB_BLOCK_LRU_LATCHES-定义数据库实例的LRU latches数
Oracle8定义了三个缓冲池:keep,recycle和default。其中default缓冲池是已经存在的。
使用多缓冲池
为一个实体建立一个默认缓冲池,语法为:
BUFFER_POOL{KEEP | RECYCLE | DEFAULT}
如何为各缓冲池设置大小
1. KEEP缓冲池
使用keep缓冲池的目的是将实体保留在内存,避免I/O操作
select physical_reads,block_gets,consistent_gets from v$buffer_pool statistics where name=’KEEP’;
计算缓冲池命中率的公式:Hit Ratio=1-physical_reads/(block_gets+consistent_gets)
2. Recycle缓冲池
使用recycle缓冲池的目的是为了清除内存中的不再使用的数据块,如果“free buffer waits”统计数总是很高,可以确定recycle缓冲池过小:
确定recycle缓冲池大小的办法:使recycle缓冲池失效运行系通到稳定状态,查看default缓冲池中由本来需要置于recycle缓冲池中数据段的缓冲区数,除以4,该结果就可以用作recycle缓冲池的大小。
3. 确定数据段置于keep还是recycle缓冲池
对于至少两倍DEFAULT缓冲池大小,并且占用系统整个I/O的一定百分比的数据段,那么最好放置于recycle缓冲池;
对于大小小于DEFAULT缓冲池的10%,并且占用至少系统整个I/O的1%的数据段,那么最好放置于keep缓冲池;
如果对表空间超过一个段时,可以通过查询V$SESSION_WAIT确定每个段的I/O操作。
如何识别和减少LRU Latch竞争
LRU latches规划了那些缓存中最近最少使用的缓冲区列表,使用DB_BLOCK_LRU_LATCHES参数可以设置数据库实例中的latches总数。
可以通过如下语句确定系统中是否有latch竞争:
select child#,sleeps/gets ratio from v$latch_children where name=’cache buffers lru chain’ ;
每个LRU latch的非命中率应少于1%,任何大于1%的latch说明存在竞争,通过如下语句查找出来:
select name from v$buffer_pool_statistics where lo_setid<=child_latch_number and hi_setid>=child_latch_numbers ;
通过增加系统的LATCHES总数和相关缓冲池的LATCHES数可以减少LRU latch竞争。所允许的LATCHES最大值应少于:number_of_cpus*2*3和number_of_buffers/50
调整排序区
如果经常进行大的排序,应增大参数SORT_AREA_SIZE的值,将参数SORT_AREA_SIZE和SORT_AREA_RETAINED_SIZE联合使用,更有利于使用大的排序区。
重新分配内存
在重新定义了oracle内存结构、调整了库快存、数据字典快存和快速缓存后,如果减少了这些结构中某一个结构的内存使用,就可能需要将内存分配到其他结构中;
在改变了oracle内存结构以后,oracle的内存需求也会改变。
减少整个内存使用
采用如下方法:
增加可用内存总数;
减少内存使用
优化数据字典高速缓存:
select sum(gets)"Read Requests",sum(getmisses)"Reads not in Memory" from v$rowcache ;
Read Requests Reads not in Memory
------------- -------------------
4764 145
命中率=Read Requests/ Reads not in Memory
若低于85% 应增加 SHARED_POOL_SIZE
优化游标:
可用以下语句检测游标的命中率:
select * from v$session_cursor_cache ;
select * from v$system_cursor_cache ;
优化游标应综合考虑,若打开的游标过多则应用程序需要的内存增大,可能发生共享池内存被换出到虚存从而影响性能。 以下三个INIT.ORA中的参数可影响游标的性能:
CLOSED_CACHED_OPEN_CURSORS 指示oracle当执行commit或rollback语句时,是否显式的关闭游标。如果游标需要反复使用可以设为false,否则应为true从而减少内存占用。
CURSOR_SPACE_FOR_TIME 若为true指示oracle只要在sql共享区中有打开的游标就一直保存该区域,若其值为false oracle可将其换出内存,即使游标仍打开。只有共享池能保存所有打开的游标时才将其设为true。
OPEN CURSORS设定一个会话可同时打开的游标数。
注释:以上增加SGA分配的调整以SGA不被换出实存为限,否则SGA部分换出实存反而降低Oracle性能。