Oracle AWR报告详细分析 (文档 ID 1523048.1)
AWR 是 Oracle 10g 版本 推出的新特性, 全称叫Automatic Workload Repository-自动负载信息库
AWR 是通过对比两次快照(snapshot)收集到的统计信息,来生成报表数据,生成的报表包括多个部分。
WORKLOAD REPOSITORY report for
DB Name | DB Id | Instance | Inst num | Release | RAC | Host |
ICCI | 1314098396 | ICCI1 | 1 | 10.2.0.3.0 | YES | HPGICCI1 |
| Snap Id | Snap Time | Sessions | Cursors/Session |
Begin Snap: | 2678 | 25-Dec-08 14:04:50 | 24 | 1.5 |
End Snap: | 2680 | 25-Dec-08 15:23:37 | 26 | 1.5 |
Elapsed: |
| 78.79 (mins) |
|
|
DB Time: |
| 11.05 (mins) |
|
|
DB Time不包括Oracle后台进程消耗的时间。如果DB Time远远小于Elapsed时间,说明数据库比较空闲。
db time= cpu time + wait time(不包含空闲等待) (非后台进程)
说白了就是db time就是记录的服务器花在数据库运算(非后台进程)和等待(非空闲等待)上的时间
DB time = cpu time + all of nonidle wait event time
在79分钟里(其间收集了3次快照数据),数据库耗时11分钟,RDA数据中显示系统有8个逻辑CPU(4个物理CPU),
平均每个CPU耗时1.4分钟,CPU利用率只有大约2%(1.4/79)。说明系统压力非常小。
列出下面这两个来做解释:
Report A:
Snap Id Snap Time Sessions Curs/Sess
--------- ------------------- -------- ---------
Begin Snap: 4610 24-Jul-08 22:00:54 68 19.1
End Snap: 4612 24-Jul-08 23:00:25 17 1.7
Elapsed: 59.51 (mins)
DB Time: 466.37 (mins)
Report B:
Snap Id Snap Time Sessions Curs/Sess
--------- ------------------- -------- ---------
Begin Snap: 3098 13-Nov-07 21:00:37 39 13.6
End Snap: 3102 13-Nov-07 22:00:15 40 16.4
Elapsed: 59.63 (mins)
DB Time: 19.49 (mins)
服务器是AIX的系统,4个双核cpu,共8个核:
/sbin> bindprocessor -q
The available processors are: 0 1 2 3 4 5 6 7
先说Report A,在snapshot间隔中,总共约60分钟,cpu就共有60*8=480分钟,DB time为466.37分钟
则:cpu花费了466.37分钟在处理Oralce非空闲等待和运算上(比方逻辑读)
也就是说cpu有 466.37/480*100% 花费在处理Oracle的操作上,这还不包括后台进程
看Report B,总共约60分钟,cpu有 19.49/480*100% 花费在处理Oracle的操作上
很显然,Report B中服务器的平均负载很低。
从awr report的Elapsed time和DB Time就能大概了解db的负载。
可是对于批量系统,数据库的工作负载总是集中在一段时间内。如果快照周期不在这一段时间内,
或者快照周期跨度太长而包含了大量的数据库空闲时间,所得出的分析结果是没有意义的.
这也说明选择分析时间段很关键,要选择能够代表性能问题的时间段。
Report Summary
Cache Sizes
| Begin | End |
|
|
Buffer Cache: | 3,344M | 3,344M | Std Block Size: | 8K |
Shared Pool Size: | 704M | 704M | Log Buffer: | 14,352K |
显示SGA中每个区域的大小(在AMM改变它们之后),可用来与初始参数值比较。
shared pool主要包括library cache和dictionary cache。
library cache用来存储最近解析(或编译)后SQL、PL/SQL和Java classes等。
dictionary cache用来存储最近引用的数据字典。
发生在library cache或dictionary cache的cache miss代价要比发生在buffer cache的代价高得多。
因此shared pool的设置要确保最近使用的数据都能被cache。
Load Profile
| Per Second | Per Transaction |
Redo size: | 918,805.72 | 775,912.72 |
Logical reads: | 3,521.77 | 2,974.06 |
Block changes: | 1,817.95 | 1,535.22 |
Physical reads: | 68.26 | 57.64 |
Physical writes: | 362.59 | 306.20 |
User calls: | 326.69 | 275.88 |
Parses: | 38.66 | 32.65 |
Hard parses: | 0.03 | 0.03 |
Sorts: | 0.61 | 0.51 |
Logons: | 0.01 | 0.01 |
Executes: | 354.34 | 299.23 |
Transactions: | 1.18 |
|
% Blocks changed per Read: | 51.62 | Recursive Call %: | 51.72 |
Rollback per transaction %: | 85.49 | Rows per Sort: | ######## |
显示数据库负载概况,将之与基线数据比较才具有更多的意义,如果每秒或每事务的负载变化不大,说明应用运行比较稳定。
单个的报告数据只说明应用的负载情况,绝大多数据并没有一个所谓“正确”的值,然而
Logons大于每秒1~2个、Hard parses大于每秒100、全部parses超过每秒300表明可能有争用问题。
Redo size:每秒产生的日志大小(单位字节),可标志数据变更频率, 数据库任务的繁重与否。
Logical reads:每秒/每事务逻辑读的块数.平决每秒产生的逻辑读的block数。Logical Reads= Consistent Gets + DB Block Gets
Block changes:每秒/每事务修改的块数
Physical reads:每秒/每事务物理读的块数
Physical writes:每秒/每事务物理写的块数
User calls:每秒/每事务用户call次数
Parses:SQL解析的次数.每秒解析次数,包括fast parse,soft parse和hard parse三种数量的综合。
软解析每秒超过300次意味着你的"应用程序"效率不高,调整session_cursor_cache。
在这里,fast parse指的是直接在PGA中命中的情况(设置了session_cached_cursors=n);
soft parse是指在shared pool中命中的情形;hard parse则是指都不命中的情况。
Hard parses:其中硬解析的次数,硬解析太多,说明SQL重用率不高。
每秒产生的硬解析次数, 每秒超过100次,就可能说明你绑定使用的不好,也可能是共享池设置不合理。
这时候可以启用参数cursor_sharing=similar|force,该参数默认值为exact。但该参数设置为similar时,存在bug,可能导致执行计划的不优。
Sorts:每秒/每事务的排序次数
Logons:每秒/每事务登录的次数
Executes:每秒/每事务SQL执行次数
Transactions:每秒事务数.每秒产生的事务数,反映数据库任务繁重与否。
Blocks changed per Read:表示逻辑读用于修改数据块的比例.在每一次逻辑读中更改的块的百分比。
Recursive Call:递归调用占所有操作的比率.递归调用的百分比,如果有很多PL/SQL,那么这个值就会比较高。
Rollback per transaction:每事务的回滚率.看回滚率是不是很高,因为回滚很耗资源 ,如果回滚率过高,
可能说明你的数据库经历了太多的无效操作 ,过多的回滚可能还会带来Undo Block的竞争
该参数计算公式如下: Round(User rollbacks / (user commits + user rollbacks) ,4)* 100% 。
Rows per Sort:每次排序的行数
Instance Efficiency Percentages (Target 100%)
Buffer Nowait %: | 100.00 | Redo NoWait %: | 100.00 |
Buffer Hit %: | 98.72 | In-memory Sort %: | 99.86 |
Library Hit %: | 99.97 | Soft Parse %: | 99.92 |
Execute to Parse %: | 89.09 | Latch Hit %: | 99.99 |
Parse CPU to Parse Elapsd %: | 7.99 | % Non-Parse CPU: | 99.95 |
本节包含了Oracle关键指标的内存命中率及其它数据库实例操作的效率。其中Buffer Hit Ratio 也称Cache Hit Ratio,
Library Hit ratio也称Library Cache Hit ratio。
同Load Profile一节相同,这一节也没有所谓“正确”的值,而只能根据应用的特点判断是否合适。
在一个使用直接读执行大型并行查询的DSS环境,20%的Buffer Hit Ratio是可以接受的,而这个值对于一个OLTP系统是完全不能接受的。
根据Oracle的经验,对于OLTP系统,Buffer Hit Ratio理想应该在90%以上。
Buffer Nowait 表示在内存获得数据的未等待比例。在缓冲区中获取Buffer的未等待比率
Buffer Nowait的这个值一般需要大于99%。否则可能存在争用,可以在后面的等待事件中进一步确认。
buffer hit 表示进程从内存中找到数据块的比率,监视这个值是否发生重大变化比这个值本身更重要。
对于一般的OLTP系统,如果此值低于80%,应该给数据库分配更多的内存。
数据块在数据缓冲区中的命中率,通常应在95%以上。否则,小于95%,需要调整重要的参数,小于90%可能是要加db_cache_size。
一个高的命中率,不一定代表这个系统的性能是最优的,比如大量的非选择性的索引被频繁访问,就会造成命中率很高的假相(大量的db file sequential read)
但是一个比较低的命中率,一般就会对这个系统的性能产生影响,需要调整。命中率的突变,往往是一个不好的信息。
如果命中率突然增大,可以检查top buffer get SQL,查看导致大量逻辑读的语句和索引,
如果命中率突然减小,可以检查top physical reads SQL,检查产生大量物理读的语句,主要是那些没有使用索引或者索引被删除的。
Redo NoWait 表示在LOG缓冲区获得BUFFER的未等待比例。如果太低(可参考90%阀值),考虑增加LOG BUFFER。
当redo buffer达到1M时,就需要写到redo log文件,所以一般当redo buffer设置超过1M,不太可能存在等待buffer空间分配的情况。
当前,一般设置为2M的redo buffer,对于内存总量来说,应该不是一个太大的值。
library hit 表示Oracle从Library Cache中检索到一个解析过的SQL或PL/SQL语句的比率,当应用程序调用SQL或存储过程时,
Oracle检查Library Cache确定是否存在解析过的版本,如果存在,Oracle立即执行语句;如果不存在,Oracle解析此语句,并在Library Cache中为它分配共享SQL区。
低的library hit ratio会导致过多的解析,增加CPU消耗,降低性能。
如果library hit ratio低于90%,可能需要调大shared pool区。
STATEMENT在共享区的命中率,通常应该保持在95%以上,否则需要要考虑:加大共享池;使用绑定变量;修改cursor_sharing等参数。
Latch Hit:Latch是一种保护内存结构的锁,可以认为是SERVER进程获取访问内存数据结构的许可。
要确保Latch Hit>99%,否则意味着Shared Pool latch争用,可能由于未共享的SQL,或者Library Cache太小,可使用绑定变更或调大Shared Pool解决。
要确保>99%,否则存在严重的性能问题。当该值出现问题的时候,我们可以借助后面的等待时间和latch分析来查找解决问题。
Parse CPU to Parse Elapsd:解析实际运行时间/(解析实际运行时间+解析中等待资源时间),越高越好。
计算公式为:Parse CPU to Parse Elapsd %= 100*(parse time cpu / parse time elapsed)。
即:解析实际运行时间/(解析实际运行时间+解析中等待资源时间)。如果该比率为100%,意味着CPU等待时间为0,没有任何等待。
Non-Parse CPU :SQL实际运行时间/(SQL实际运行时间+SQL解析时间),太低表示解析消耗时间过多。
计算公式为:% Non-Parse CPU =round(100*1-PARSE_CPU/TOT_CPU),2)。如果这个值比较小,表示解析消耗的CPU时间过多。
与PARSE_CPU相比,如果TOT_CPU很高,这个比值将接近100%,这是很好的,说明计算机执行的大部分工作是执行查询的工作,而不是分析查询的工作。
Execute to Parse:是语句执行与分析的比例,如果要SQL重用率高,则这个比例会很高。该值越高表示一次解析后被重复执行的次数越多。
计算公式为:Execute to Parse =100 * (1 - Parses/Executions)。
本例中,差不多每execution 5次需要一次parse。所以如果系统Parses > Executions,就可能出现该比率小于0的情况。
该值<0通常说明shared pool设置或者语句效率存在问题,造成反复解析,reparse可能较严重,或者是可能同snapshot有关,通常说明数据库性能存在问题。
In-memory Sort:在内存中排序的比率,如果过低说明有大量的排序在临时表空间中进行。
考虑调大PGA(10g)。如果低于95%,可以通过适当调大初始化参数PGA_AGGREGATE_TARGET或者SORT_AREA_SIZE来解决,
注意这两个参数设置作用的范围时不同的,SORT_AREA_SIZE是针对每个session设置的,PGA_AGGREGATE_TARGET则时针对所有的sesion的。
Soft Parse:软解析的百分比(softs/softs+hards),近似当作sql在共享区的命中率,太低则需要调整应用使用绑定变量。
sql在共享区的命中率,小于<95%,需要考虑绑定,如果低于80%,那么就可以认为sql基本没有被重用。
Shared Pool Statistics
| Begin | End |
Memory Usage %: | 47.19 | 47.50 |
% SQL with executions>1: | 88.48 | 79.81 |
% Memory for SQL w/exec>1: | 79.99 | 73.52 |
Memory Usage %:对于一个已经运行一段时间的数据库来说,共享池内存使用率,应该稳定在75%-90%间,
如果太小,说明Shared Pool有浪费,而如果高于90,说明共享池中有争用,内存不足。
这个数字应该长时间稳定在75%~90%。如果这个百分比太低,表明共享池设置过大,带来额外的管理上的负担,从而在某些条件下会导致性能的下降。
如果这个百分率太高,会使共享池外部的组件老化,如果SQL语句被再次执行,这将使得SQL语句被硬解析。
在一个大小合适的系统中,共享池的使用率将处于75%到略低于90%的范围内.
SQL with executions>1:执行次数大于1的sql比率,如果此值太小,说明需要在应用中更多使用绑定变量,避免过多SQL解析。
在一个趋向于循环运行的系统中,必须认真考虑这个数字。在这个循环系统中,在一天中相对于另一部分时间的部分时间里执行了一组不同的SQL语句。
在共享池中,在观察期间将有一组未被执行过的SQL语句,这仅仅是因为要执行它们的语句在观察期间没有运行。只有系统连续运行相同的SQL语句组,这个数字才会接近100%。
Memory for SQL w/exec>1:执行次数大于1的SQL消耗内存的占比。
这是与不频繁使用的SQL语句相比,频繁使用的SQL语句消耗内存多少的一个度量。
这个数字将在总体上与% SQL with executions>1非常接近,除非有某些查询任务消耗的内存没有规律。
在稳定状态下,总体上会看见随着时间的推移大约有75%~85%的共享池被使用。如果Statspack报表的时间窗口足够大到覆盖所有的周期,
执行次数大于一次的SQL语句的百分率应该接近于100%。这是一个受观察之间持续时间影响的统计数字。可以期望它随观察之间的时间长度增大而增大。
Top 5 Timed Events
Event | Waits | Time(s) | Avg Wait(ms) | % Total Call Time | Wait Class |
CPU time |
| 515 |
| 77.6 |
|
SQL*Net more data from client | 27,319 | 64 | 2 | 9.7 | Network |
log file parallel write | 5,497 | 47 | 9 | 7.1 | System I/O |
db file sequential read | 7,900 | 35 | 4 | 5.3 | User I/O |
db file parallel write | 4,806 | 34 | 7 | 5.1 | System I/O |
这是报告概要的最后一节,显示了系统中最严重的5个等待,按所占等待时间的比例倒序列示。当我们调优时,总希望观察到最显著的效果,
因此应当从这里入手确定我们下一步做什么。
例如 如果‘buffer busy wait’是较严重的等待事件,我们应当继续研究报告中Buffer Wait和File/Tablespace IO区的内容,
识别哪些文件导致了问题。如果最严重的等待事件是I/O事件,我们应当研究按物理读排序的SQL语句区以识别哪些语句在
执行大量I/O,并研究Tablespace和I/O区观察较慢响应时间的文件。如果有较高的LATCH等待,就需要察看详细的LATCH
统计识别哪些LATCH产生的问题。
一个性能良好的系统,cpu time应该在top 5的前面,否则说明你的系统大部分时间都用在等待上。
在这里,log file parallel write是相对比较多的等待,占用了7%的CPU时间。
通常,在没有问题的数据库中,CPU time总是列在第一个。
对于常见的等待事件,说明如下:
db file scattered read 文件分散读取
该事件通常与全表扫描或者fast full index scan有关。因为全表扫描是被放入内存中进行的进行的,通常情况下基于性能的考虑,有时候也可能是分配不到足够长的连续内存空间,所以会将数据块分散(scattered)读入Buffer Cache中。该等待过大可能是缺少索引或者没有合适的索引(可以调整optimizer_index_cost_adj) 。这种情况也可能是正常的,因为执行全表扫描可能比索引扫描效率更高。当系统存在这些等待时,需要通过检查来确定全表扫描是否必需的来调整。因为全表扫描被置于LRU(Least Recently Used,最近最少适用)列表的冷端(cold end),对于频繁访问的较小的数据表,可以选择把他们Cache 到内存中,以避免反复读取。当这个等待事件比较显著时,可以结合v$session_longops 动态性能视图来进行诊断,该视图中记录了长时间(运行时间超过6 秒的)运行的事物,可能很多是全表扫描操作(不管怎样,这部分信息都是值得我们注意的)。
关于参数OPTIMIZER_INDEX_COST_ADJ=n:该参数是一个百分比值,缺省值为100,可以理解为FULL SCAN COST/INDEX SCAN COST。当n%* INDEX SCAN COST<FULL SCAN COST时,oracle会选择使用索引。在具体设置的时候,我们可以根据具体的语句来调整该值。如果我们希望某个statement使用索引,而实际它确走全表扫描,可以对比这两种情况的执行计划不同的COST,从而设置一个更合适的值。
db file sequential read 文件顺序读取整代码,特别是表连接:该事件说明在单个数据块上大量等待,该值过高通常是由于表间连接顺序很糟糕(没有正确选择驱动行源),或者使用了非选择性索引。通过将这种等待与statspack报表中已知其它问题联系起来(如效率不高的sql),通过检查确保索引扫描是必须的,并确保多表连接的连接顺序来调整。
buffer busy wait 缓冲区忙 增大DB_CACHE_SIZE,加速检查点,调整代码:
latch free:当闩锁丢失率高于0.5%时,需要调整这个问题。详细的我们在后面的Latch Activity for DB部分说明。
Free Buffer 释放缓冲区:这个等待事件表明系统正在等待内存中的可用空间,这说明当前Buffer 中已经没有Free 的内存空间。如果应用设计良好,SQL 书写规范,充分绑定变量,那这种等待可能说明Buffer Cache 设置的偏小,你可能需要增大DB_CACHE_SIZE。该等待也可能说明DBWR的写出速度不够,或者磁盘存在严重的竞争,可以需要考虑增加检查点、使用更多的DBWR 进程,或者增加物理磁盘的数量,分散负载,平衡IO。
log file parallel write:从log buffer 写redo 记录到redo log 文件,主要指常规写操作(相对于log file sync)。如果你的Log group 存在多个组成员,当flush log buffer 时,写操作是并行的,这时候此等待事件可能出现。尽管这个写操作并行处理,直到所有I/O 操作完成该写操作才会完成(如果你的磁盘支持异步IO或者使用IO SLAVE,那么即使只有一个redo log file member,也有可能出现此等待)。这个参数和log file sync 时间相比较可以用来衡量log file 的写入成本。通常称为同步成本率。改善这个等待的方法是将redo logs放到I/O快的盘中,尽量不使用raid5,确保表空间不是处在热备模式下,确保redo log和data的数据文件位于不同的磁盘中。
log file sync:当一个用户提交或回滚数据时,LGWR将会话的redo记录从日志缓冲区填充到日志文件中,用户的进程必须等待这个填充工作完成。在每次提交时都出现,如果这个等待事件影响到数据库性能,那么就需要修改应用程序的提交频率, 为减少这个等待事件,须一次提交更多记录,或者将重做日志REDO LOG 文件访在不同的物理磁盘上,提高I/O的性能。
log buffer space:日志缓冲区写的速度快于LGWR写REDOFILE的速度,可以增大日志文件大小,增加日志缓冲区的大小,或者使用更快的磁盘来写数据。当你日志缓冲(log buffer)产生重做日志的速度比LGWR 的写出速度快,或者是当日志切换(log switch)太慢时,就会发生这种等待。这个等待出现时,通常表明redo log buffer 过小,为解决这个问题,可以考虑增大日志文件的大小,或者增加日志缓冲器的大小。另外一个可能的原因是磁盘I/O 存在瓶颈,可以考虑使用写入速度更快的磁盘。在允许的条件下设置可以考虑使用裸设备来存放日志文件,提高写入效率。在一般的系统中,最低的标准是,不要把日志文件和数据文件存放在一起,因为通常日志文件只写不读,分离存放可以获得性能提升。
logfile switch:通常是因为归档速度不够快。表示所有的提交(commit)的请求都需要等待"日志文件切换"的完成。Log file Switch 主要包含两个子事件:
log file switch (archiving needed) 这个等待事件出现时通常是因为日志组循环写满以后,第一个日志归档尚未完成,出现该等待。出现该等待,可能表示io 存在问题。解决办法:①可以考虑增大日志文件和增加日志组;②移动归档文件到快速磁盘;③调整log_archive_max_processes。
log file switch (checkpoint incomplete) 当日志组都写完以后,LGWR 试图写第一个log file,如果这时数据库没有完成写出记录在第一个log file 中的dirty 块时(例如第一个检查点未完成),该等待事件出现。该等待事件通常表示你的DBWR 写出速度太慢或者IO 存在问题。为解决该问题,你可能需要考虑增加额外的DBWR 或者增加你的日志组或日志文件大小,或者也可以考虑增加checkpoint的频率。
DB File Parallel Write:文件被DBWR并行写时发生。解决办法:改善IO性能。
DB File Single Write:当文件头或别的单独块被写入时发生,这一等待直到所有的I/O调用完成。解决办法:改善IO性能。
DB FILE Scattered Read:当扫描整个段来根据初始化参数db_file_multiblock_read_count读取多个块时发生,因为数据可能分散在不同的部分,这与分条或分段)相关,因此通常需要多个分散的读来读取所有的数据。等待时间是完成所有I/O调用的时间。解决办法:改善IO性能。
Direct Path Read:一般直接路径读取是指将数据块直接读入PGA中。一般用于排序、并行查询和read ahead操作。这个等待可能是由于I/O造成的。使用异步I/O模式或者限制排序在磁盘上,可能会降低这里的等待时间。
direct path write:直接路径写该等待发生在,系统等待确认所有未完成的异步I/O 都已写入磁盘。对于这一写入等待,我们应该找到I/O 操作最为频繁的数据文件(如果有过多的排序操作,很有可能就是临时文件),分散负载,加快其写入操作。如果系统存在过多的磁盘排序,会导致临时表空间操作频繁,对于这种情况,可以考虑使用Local管理表空间,分成多个小文件,写入不同磁盘或者裸设备。
control file parallel write:当server 进程更新所有控制文件时,这个事件可能出现。如果等待很短,可以不用考虑。如果等待时间较长,检查存放控制文件的物理磁盘I/O 是否存在瓶颈。
多个控制文件是完全相同的拷贝,用于镜像以提高安全性。对于业务系统,多个控制文件应该存放在不同的磁盘上,一般来说三个是足够的,如果只有两个物理硬盘,那么两个控制文件也是可以接受的。在同一个磁盘上保存多个控制文件是不具备实际意义的。减少这个等待,可以考虑如下方法:①减少控制文件的个数(在确保安全的前提下)。②如果系统支持,使用异步IO。③转移控制文件到IO 负担轻的物理磁盘。
control file sequential read /control file single write :控制文件连续读/控制文件单个写对单个控制文件I/O 存在问题时,这两个事件会出现。如果等待比较明显,检查单个控制文件,看存放位置是否存在I/O 瓶颈。
下面是关于这里的常见的等待事件和解决方法的一个快速预览
等待事件 | 一般解决方法 |
Sequential Read | 调整相关的索引和选择合适的驱动行源 |
Scattered Read | 表明出现很多全表扫描。优化code,cache小表到内存中。 |
Free Buffer | 增大DB_CACHE_SIZE,增大checkpoint的频率,优化代码 |
Buffer Busy Segment header | 增加freelist或者freelistgroups |
Buffer Busy Data block | 隔离热块;使用反转索引;使用更小的块;增大表的initrans |
Buffer Busy Undo header | 增加回滚段的数量或者大小 |
Buffer Busy Undo block | Commit more;增加回滚段的数量或者大小 |
Latch Free | 检查具体的等待latch类型,解决方法参考后面介绍 |
Enqueue–ST | 使用本地管理的表空间或者增加预分配的盘区大小 |
Enqueue–HW | 在HWM之上预先分配盘区 |
Enqueue–TX4 | 在表或者索引上增大initrans的值或者使用更小的块 |
Log Buffer Space | 增大LOG_BUFFER,改善I/O |
Log File Switch | 增加或者增大日志文件 |
Log file sync | 减小提交的频率;使用更快的I/O;或者使用裸设备 |
Write complete waits | 增加DBWR;提高CKPT的频率; |
SQL Statistics v$sqlarea
- SQL ordered by Elapsed Time
- SQL ordered by CPU Time
- SQL ordered by Gets
- SQL ordered by Reads
- SQL ordered by Executions
- SQL ordered by Parse Calls
- SQL ordered by Sharable Memory
- SQL ordered by Version Count
- SQL ordered by Cluster Wait Time
- Complete List of SQL Text
本节按各种资源分别列出对资源消耗最严重的SQL语句,并显示它们所占统计期内全部资源的比例,这给出我们调优指南。例如在一个系统中,CPU资源是系统性能瓶颈所在,那么优化buffer gets最多的SQL语句将获得最大效果。在一个I/O等待是最严重事件的系统中,调优的目标应该是physical IOs最多的SQL语句。
SQL ordered by Gets
- Resources reported for PL/SQL code includes the resources used by all SQL statements called by the code.
- Total Buffer Gets: 16,648,792
- Captured SQL account for 97.9% of Total
这一部分,通过Buffer Gets对SQL语句进行排序,即通过它执行了多少个逻辑I/O来排序。顶端的注释表明一个PL/SQL单元的缓存获得(Buffer Gets)包括被这个代码块执行的所有SQL语句的Buffer Gets。因此将经常在这个列表的顶端看到PL/SQL过程,因为存储过程执行的单独的语句的数目被总计出来。在这里的Buffer Gets是一个累积值,所以这个值大并不一定意味着这条语句的性能存在问题。通常我们可以通过对比该条语句的Buffer Gets和physical reads值,如果这两个比较接近,肯定这条语句是存在问题的,我们可以通过执行计划来分析,为什么physical reads的值如此之高。另外,我们在这里也可以关注gets per exec的值,这个值如果太大,表明这条语句可能使用了一个比较差的索引或者使用了不当的表连接。
另外说明一点:大量的逻辑读往往伴随着较高的CPU消耗。所以很多时候我们看到的系统CPU将近100%的时候,很多时候就是SQL语句造成的,这时候我们可以分析一下这里逻辑读大的SQL。
SQL ordered by Reads
- Total Disk Reads: 322,678
- Captured SQL account for 66.1% of Total
这部分通过物理读对SQL语句进行排序。这显示引起大部分对这个系统进行读取活动的SQL,即物理I/O。当我们的系统如果存在I/O瓶颈时,需要关注这里I/O操作比较多的语句。
SQL ordered by Executions
- Total Executions: 1,675,112
- Captured SQL account for 99.8% of Total
这部分告诉我们在这段时间中执行次数最多的SQL语句。为了隔离某些频繁执行的查询,以观察是否有某些更改逻辑的方法以避免必须如此频繁的执行这些查询,这可能是很有用的。或许一个查询正在一个循环的内部执行,而且它可能在循环的外部执行一次,可以设计简单的算法更改以减少必须执行这个查询的次数。即使它运行的飞快,任何被执行几百万次的操作都将开始耗尽大量的时间。
SQL ordered by Parse Calls
- Total Parse Calls: 182,780
- Captured SQL account for 99.0% of Total
在这一部分,主要显示PARSE与EXECUTIONS的对比情况。如果PARSE/EXECUTIONS>1,往往说明这个语句可能存在问题:没有使用绑定变量,共享池设置太小,cursor_sharing被设置为exact,没有设置session_cached_cursors等等问题。
Instance Activity Statistics
- Instance Activity Stats
- Instance Activity Stats - Absolute Values
- Instance Activity Stats - Thread Activity
dirty buffers inspected | 25,007 | 5.29 | 4.47 |
脏数据从LRU列表中老化,A value here indicates that the DBWR is not keeping up。如果这个值大于0,就需要考虑增加DBWRs。 dirty buffers inspected: This is the number of dirty (modified) data buffers that were aged out on the LRU list. You may benefit by adding more DBWRs.If it is greater than 0, consider increasing the database writes. |
sorts (disk) | 4 | 0.00 | 0.00 |
磁盘排序一般不能超过5%。如果超过5%,需要设置参数PGA_AGGREGATE_TARGET或者SORT_AREA_SIZE,注意,这里SORT_AREA_SIZE是分配给每个用户的,PGA_AGGREGATE_TARGET则是针对所有的session的一个总数设置。 |
table fetch continued row | 0 | 0.00 | 0.00 |
这是发生行迁移的行。当行迁移的情况比较严重时,需要对这部分进行优化。 检查行迁移的方法: 1) 运行$ORACLE_HOME/rdbms/admin/utlchain.sql 2) analyze table table_name list chained rows into CHAINED_ROWS 3) select * from CHAINED_ROWS where table_name='table_name'; 清除的方法: 方法1:create table table_name_tmp as select * from table_name where rowed in (select head_rowid from chained_rows); Delete from table_name where rowed in (select head_rowid from chained_rows); Insert into table_name select * from table_name_tmp; 方法2:create table table_name_tmp select * from table_name ; truncate table table_name insert into table_name select * from table_name_tmp 方法3:用exp工具导出表,然后删除这个表,最后用imp工具导入这表 方法4:alter table table_name move tablespace tablespace_name,然后再重新表的索引 上面的4种方法可以用以消除已经存在的行迁移现象,但是行迁移的产生很多情况下时由于PCT_FREE参数设置的太小所导致,所以需要调整PCT_FREE参数的值。 |
IO Stats
EAS_D_EAS_INDEX | /u01/oradata/EAS_D_EAS_INDEX.ora | 374,853 | 2 | 3.23 | 8.88 | 2 | 0.69 | 14,896 | 0 | 9 | 54.44 |
EAS_D_EAS_STANDARD | /u01/oradata/EAS_D_EAS_STANDARD.ora | 2,383,939 | 14 | 1.62 | 22.20 | 10 | 0.16 | 138,085 | 1 | 103 | 12.43 |
EAS_D_EAS_STANDARD | /u01/oradata/EAS_D_EAS_STANDARD02.ora | 4,033,519 | 24 | 1.14 | 11.38 | 20 | 0.24 | 186,396 | 1 | 677 | 12.39 |
EAS_D_EAS_TEMP2 | /u01/oradata/EAS_D_EAS_TEMP2 | 45,508 | 0 | 2.61 | 12.16 | 0 | 1.04 | 31,062 | 0 | 10 | 0.00 |
EAS_T_EAS_STANDARD | /u01/oradata/EAS_T_EAS_STANDARD.ora | 61,026 | 0 | 0.55 | 9.51 | 0 | 9.06 | 34,883 | 0 | 0 | |
RMAN_TBS | /u01/oradata/rman_tbs.dbf | 1,634 | 0 | 1.65 | 5.58 | 0 | 0.14 | 287 | 0 | 0 | 0.00 |
SYSAUX | /u01/oradata/easdb/sysaux01.dbf | 188,134 | 1 | 5.69 | 19.04 | 1 | 0.12 | 58,653 | 0 | 1 | 0.00 |
SYSTEM | /u01/oradata/easdb/system01.dbf | 104,452 | 1 | 3.88 | 9.27 | 1 | 1.17 | 40,351 | 0 | 49 | 289.59 |
TEMP | /u01/oradata/easdb/temp01.dbf | 236 | 0 | 59.66 | 16.90 | 0 | 83.81 | 412 | 0 | 0 | |
UNDOTBS1 | /u01/oradata/easdb/undotbs01.dbf | 4,017 | 0 | 29.21 | 62.16 | 0 | 0.51 | 119,610 | 1 | 179 | 0.00 |
USERS | /u01/oradata/easdb/users01.dbf | 120 | 0 | 5.42 | 7.81 | 0 | 0.84 | 45 | 0 | 0 | 0.00 |
在这里主要关注Av Rd(ms)列 (reads per millisecond)的值,一般来说,大部分的磁盘系统的这个值都能调整到14ms以下,oracle认为该值超过20ms都是不必要的。如果该值超过1000ms,基本可以肯定存在I/O的性能瓶颈。如果在这一列上出现######,可能是你的系统存在严重的I/O问题,也可能是格式的显示问题。
当出现上面的问题,我们可以考虑以下的方法:
1)优化操作该表空间或者文件的相关的语句。
2)如果该表空间包含了索引,可以考虑压缩索引,是索引的分布空间减小,从而减小I/O。
3)将该表空间分散在多个逻辑卷中,平衡I/O的负载。
4)我们可以通过设置参数DB_FILE_MULTIBLOCK_READ_COUNT来调整读取的并行度,这将提高全表扫描的效率。但是也会带来一个问题,就是oracle会因此更多的使用全表扫描而放弃某些索引的使用。为解决这个问题,我们需要设置另外一个参数OPTIMIZER_INDEX_COST_ADJ=30(一般建议设置10-50)。
关于OPTIMIZER_INDEX_COST_ADJ=n:该参数是一个百分比值,缺省值为100,可以理解为FULL SCAN COST/INDEX SCAN COST。当n%* INDEX SCAN COST<FULL SCAN COST时,oracle会选择使用索引。在具体设置的时候,我们可以根据具体的语句来调整该值。如果我们希望某个statement使用索引,而实际它确走全表扫描,可以对比这两种情况的执行计划不同的COST,从而设置一个更合适的值。
5)检查并调整I/O设备的性能。
Tablespace IO Stats
- ordered by IOs (Reads + Writes) desc
Tablespace | Reads | Av Reads/s | Av Rd(ms) | Av Blks/Rd | Writes | Av Writes/s | Buffer Waits | Av Buf Wt(ms) |
ICCIDAT01 | 67,408 | 14 | 3.76 | 3.17 | 160,261 | 34 | 6 | 0.00 |
UNDOTBS1 | 10 | 0 | 12.00 | 1.00 | 57,771 | 12 | 625 | 0.02 |
TEMP | 15,022 | 3 | 8.74 | 7.24 | 3,831 | 1 | 0 | 0.00 |
USERS | 68 | 0 | 5.44 | 1.00 | 971 | 0 | 0 | 0.00 |
SYSAUX | 263 | 0 | 5.48 | 1.00 | 458 | 0 | 0 | 0.00 |
SYSTEM | 32 | 0 | 5.94 | 1.00 | 158 | 0 | 3 | 23.33 |
UNDOTBS2 | 6 | 0 | 16.67 | 1.00 | 6 | 0 | 0 | 0.00 |
显示每个表空间的I/O统计。根据Oracle经验,Av Rd(ms) [Average Reads in milliseconds]不应该超过30,否则认为有I/O争用。