某客户的操作人员反应很慢不能操作,管理人员登录小机系统后发现cpu使用到了95%以上。而且这种情况持续了几个月。小机是ibm的p520,配置是2颗4核的cpu,内存是48g,oracle是10.2.0.5。topas与生成的awr报告如下:
从上面的load profile部分可以看到每秒执行的sql与事务数并不高,因为是周末并没有太多人使用系统。
从上面的top 等待事件来看主要是cpu time。查看这个时间段生成的addm报告:
从上面的信息addm报告与top sql部分可以看到在快照26245到26246之间database time为16644秒。而找到的一条sql消耗了76%的cpu时间。如果对这两条sql执行优化应该可以将cpu消耗显著降低。而该sql虽然每执行一次的时间是0.93秒,消耗的cpu时间只有0.76秒,但在周末的时间内一个小时都执行了16,029次,消耗的cpu时间是12249秒而且小机的cpu数量只有2颗(6核),那么每秒该sql的执行次数就是=16029/3600=4.5次,所以大部分的cpu被该sql所消耗了。这还是周末,如果上班时间该sql执行的次数会以倍数增加,那么cpu的消耗就会更高。
sql语句如下:
其执行计划如下:
从执行计划来看该sql的cost也不高(执行时间是0.93秒,cpu时间是0.76秒),从sql的执行计划来看见两个表是使用的嵌套循环,而驱动表t_lk_email_emailgroup的数据量是1w多行,t_lk_email_detail表的数量是20w行左右。而表t_lk_email_emailgroup执行全表扫描后满足查询条件的记录有4条,所以就得对表t_lk_email_detail中的记录遍历4次来找到与驱动表相匹配的记录,虽然每次执行时间不长,但是在并发执行次数高,而物理cpu数量不足的情况下还是会引发性能问题。而这两个表有等值连接条件f_email_group_id,而且在驱动表中f_email_group_id列创建了索引,所以这里选择在表t_lk_email_detail表的f_email_group_id列上创建索引之后执行计划如下所示:
sql执行计划的cost显示增加了,但sql执行时间只有0.1s提高了10倍。在对该sql优化之后,业务系统恢复正常,cpu使用率也维持在20%左右。
所以在优化时,不能简单的根据sql执行时间来判断该sql是否会引发性能问题,要具体问题具体分析。