前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >提升高度,综合SQL上下文进行逻辑优化

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

作者头像
老虎刘
发布2022-06-22 17:46:40
发布2022-06-22 17:46:40
2150
举报

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

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

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

两个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没有优化,随着表的记录数逐步增加,性能会越来越差。而使用了索引,记录数的增加对性能的影响微乎其微。这就是优化起到的作用!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-08-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老虎刘谈oracle性能优化 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档