statspack系列8
原文:http://jonathanlewis.wordpress.com/2006/12/27/analysing-statspack-8/
作者:Jonathan Lewis
在前面的关于statspack的文章中,我引用了Don Burleson发表的文章中的一些数字。
这是oracle 10g的数据库设置了过小的log buffer的例子,大小为512K.
Top 5 Timed Events ~~~~~~~~~~~~~~~~~~ % Total Event Waits Time (s) DB Time Wait Class log file parallel write 9,670 291 55.67 System I/O log file sync 9,293 278 53.12 Commit CPU time 225 43.12 db file parallel write 4,922 201 38.53 System I/O control file parallel write 1,282 65 12.42 System I/O
在Burleson的站点上,我发现了这个片段的出处。
报告是一个word文档,在这个链接this URL处,是在Burleson Consulting Oracle Forum的一个回帖中被引用,在继续写这篇博客之前,应该好好看看这个帖子,其中讨论了许多报告中的统计信息,和一些前瞻性的建议。为了达到互相借鉴的目的,你可以在阅读本篇博客的时候再开一关于这个报告的窗口。
更新14th Nov 2007:尽管论坛的帖子还在,但文档已经从站点移除了,帖子的最新版本现在生成了一个7页得pdf文档,早些的版本还能在google的缓存中发现。
首先,这是一个有4GB内存和raid-5磁盘配置的linux系统,这是一个专用的服务器,没有其它的任务在处理,在阅读statspack报告时,不要忽略这些信息,这些信息通常可以告诉你那些统计是合理的,哪些不合理。
报告同时显示,机器有两颗cpu,快照的间隔时间是一个小时。在看load profiles和waits之前,先看一下buffer cache(124M), shared pool(136M)的大小,现在系统还留下大约3.7GB大小的内存未使用,快速的check一下参数列表, pga_aggregate_target参数显示,传言oracle对于进程的内存使用有一个92MB的限制,另外在看sga_target设置是280MB大小,所以看到数据库仅仅300MB大小。
所以,拥有4GB大小的内存,但却使用300M大小的数据库,况且系统再没有其它任务在运行,为什么不把buffer cache设置的更大一些,让整个数据库的操作都在内存中完成呢!(这是在阅读awr report时我记录下的一个问题,后面可以继续跟踪一下,虽然它不能解决性能问题,但这个一个在设置参数的策略问题).
下面来看一个load profile:每秒7KB大小的redo日志,每秒464个逻辑I/O,52个块更改,1个物理读,2个物理写,2.66个事务。*均下来数据库是很空闲的。再看一下top 5的等待时间,(两颗cpu,意味着7,200s的cpu时间,但仅仅有226s在使用),所以*均下来数据库依然没有什么压力。
但是这个是statspack的一个缺点,*均值会丢失一些重要的信息,或许这个系统的问题就是有大量的活动触发而造成在短时间内数据库很慢。而报告,作为一个健康性检查,通常情况下就是粗略的review。所以,如果没有特别具体的问题去跟踪,那么就找下效率不高的地方。
看一下load profile和wait events,好像没有什么好说的,我们已经得到一个事实,系统没有太多的任务处理,*均的I/O比较慢(可能跟raid-5的配置有关)。
查看第六页(service statistisc),我们发现DBA已经启动系统来来使用数据库的服务,大部分的任务都是通过服务来完成。
再回到系统的统计上,唯一例外的数据就是“index fast full scan(fast)”,如果这是一个OLTP系统的话,那么这是一个资源密集型的执行计划路径,一个小时内有2,941次。
再看一下解析的数量,一个小时72,000次,*均下来20次/s,这并不是大的灾难,但或许可以避免,所以看一下统计信息“session cursor cache hits”, 数组是0;然后再看一下参数session_cached_cursors设置成了0,这可能是一个错误,最好是设置是像50这样的数字,这会使用一点内存(实质上我们有很多),来消除花费在parse call上的cpu时间。
快速的看下redo的指标:redo大小加上redo的浪费的大约31M, redo的block写大约是63,698,所以redo block的大小是512bytes,“redo synch writes”是9,280,与“redo writes” 9,678非常相*,(与后面的“user commits“ 的数量非常相*,*均每次7个block的大小,非常的类似于有很多小事务的OLTP系统)。
到table scan的部分,会发现有些震惊的数据,通过rowid获取了138,713行数据,75million fetched 通过table scan(大约是1.17Million的块扫描)。大部分的tablescans是小表的扫描,所以基本上是缓存的。少量的大表table scans(忽略特殊的情况,小表占了2%的buffer cache,即26MB的空间,大约3,300个块)。
如果在这片报告中(除了慢的磁盘)还有一些东西需要client知道的话,那就是开发应用程序人员需要review一些他们的数据和代码,看下是否有合适的索引来满足需求。如果有合适的索引,需要检查一下统计信息,看下为什么oracle没有使用索引。
在第十一页的Instance Activity Stats上,log files的大小是10M,对于大多数系统来说还是设置的略显小了,但在一个小的系统上,每小时3次的log switch看起来也是合适的,或许我们要想客户提一下参数archive_lag_target,并解释下如何设置这个参数来保证在每N s的时候保证一次log switch。
在第十四页的Buffer Pool Advisory显示了一个有趣的模型,当把buffer cache从60M调整到72M的时候,物理读会显著的下降。如果你赞同这样的建议,你肯定系统调整下cache的大小。
PGA Aggr Histogram的意义通常都没那么大,在这个例子中更是特别小。这个指标可能给我们一个警示,对于真正的OLTP系统sort/hash操作会有点太多,这里pga_aggregate_target仅仅96M,对于processes设置成150而言,或许有点小了,对于OLTP系统来说,每个process合适的大小是2M-4M大小。这个建议分配更多一点内存给pga和sga。
Latch的活动指标或许没有什么兴趣,值得一看的是“row cache objects“相对比”library cache latch“要大。这可能是过度的优化的指示(a.k.a. “hard” parsing),但是因为没有太多的hard parse,并且高的指标主要来自dc_global_oids, dc_object_ids, and dc_users caches。这可能在object table类型上使用cast()函数而带来的负影响,对于高性能,高并发的系统而言,这不是oracle里亲和的技术。
Library Cache Activity显示了一些reloads操作,可能意味着要增加shared pool的大小,也有可能是使用了字面量,但是在当前的系统负载压力下,这不会是一个大问题,cursor_sharing参数设置为force,所以要坚持一下代码中时候掺杂了绑定变量和字面量。这是一个该指令不适用于在更高版本的Oracle的代码风格。
再看下其它参数,我们可能想处理db_file_mulitblock_read_count这个参数,并且保证每一个进程db_cache_size大小都至少1M.
总结:
如果你想对数据库进行快速的检查:
磁盘写的速度比较慢-可能是因为RAID-5.
因为index的错误,不合适的统计信息,或者代码的问题,导致一些查询非常低效。你可以使用机器的内存,把更多的数据放进sga和pga中,目前这种方式因为大量的资源浪费在tablescan上,而不会有很大的改观。
参数session_cached_cursor 设置成非零的值,可能节省一点cpu。
保证代码的风格是正确的,而不再使用cursor_sharing = force。
在使用包括类似于cast函数这样的sql时要特别小心。
这个是花费了90分钟的review(包括了打字时间),所以如果你任务还有一些东西值得提起,或者是文章的一些东西不相关,下面可以进行自由评论。