oracle 逻辑优化,提升高度,综合SQL上下文进行逻辑优化

之前我们的优化都是针对单个SQL的优化,但是很多时候SQL是出现在存储过程中,有上下文语境。如果我们能够通过分析业务逻辑,对某段SQL做一个整体优化,那样带来的效果可能会更加显著。

我们在对一个生产系统的AWR报告中逐个TOP SQL进行分析的时候,发现TOP4 的存储过程,包含了TOP9和TOP23,两个SQL的执行时间都比较长(平均执行时间分别是442秒和171秒),一般SQL执行时间越长越容易进行优化:

53b5a4e496bcb182542dd9a22452fe1f.png

截取的TOP4存储过程中的关键代码段:

c52389b66b701b772ac1d279b78c7b7c.png

两个SQL都非常简单,TP_INFOCHECK_RESULT表有9300多万条记录,其中DEAL_TAG字段有4个唯一值,很明显没有索引。

分析与优化建议:

TOP23的优化:

根据TOP23的update语句,虽然DEAL_TAG字段的唯一值少,而且DEAL_TAG='T'的记录数还可能非常多,但是由于每次只取4000条(RONUM<4001),这个字段上明显需要创建一个索引。

如果没有索引,当DEAL_TAG大部分记录为T的时候,全表扫描只需要扫描一部分block,得到满足条件的4000条件记录就停止了,性能不会差;但是随着不断的update,DEAL_TAG=‘T’的记录越来越少,基本上就相当于要对这个9300万的表做全表扫描了。

预计创建索引后这个update sql的平均执行时间应该1秒左右。

TOP9的优化:

再来看top9,没有DEAL_TAG字段的索引时,每次都要做全表扫描,每次执行需要442秒。即使创建了索引,在DEAL_TAG记录数多的时候,也需要扫描很多的索引block,才能计算出=‘T’的记录总数。

结合存储过程的上下文,做count(*)只是为了判断记录数是否为0,那么我们就可以把rownum=1 作为一个新增的谓词条件加到SQL里面,虽然SQL的逻辑改变了,但是对于整个存储过程的逻辑是没有变化的。

即:select count(*) INTO v_cnt FROM TP_INFOCHECK_RESULT where deal_tag='T' and rownum=1;

加了rownum=1后,这个select count(*)的SQL应该只需要1毫秒左右就能完成。这个SQL就会从原来的top9 ,变成一个基本不消耗资源可以忽略不计的SQL了。

总结:

索引的使用仍是本案例的最大功臣,但是如果我们再仔细对存储过程上下文进行综合分析,还是有可能发现一些逻辑上可以优化的部分,还可以进一步的节约系统资源。类似判断记录是否存在的业务逻辑应该还是比较常见的,如果是不求具体值,只问有没有,那么就可以通过本文的方法进行处理。优化前,这两个SQL使用了大量的CPU和IO资源,而优化后,这些资源的使用基本上可以忽略不计了(当然,新增的索引还是会在表做DML操作时多一步索引维护动作)。

很多时候,系统不是资源不够,而是资源没有合理的使用。如果SQL没有优化,随着表的记录数逐步增加,性能会越来越差。而使用了索引,记录数的增加对性能的影响微乎其微。这就是优化起到的作用!

公众号留言功能已开通,欢迎大家拍砖!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值