背景:各个企业的记账系统,都超级复杂,超级重要,每一笔帐,对应的就是钱。而账务系统区别与前端在线业务系统,又有其处理记账过程中锁的问题,事务量较大等问题。考验开发水平的同时,也考验着后端的基础架构部门,运维部门。以下有脱敏部分,但实际经验都是来源于我们的生产系统。目前我们的账务系统,在面对高并发提交下的log file sync问题,以及索引分裂问题。我们逐渐去优化它。
如下是我们生产系统账务的耗时情况
阶段一:账务系统的耗时一直在往上彪,面对前端业务的考验,协同开发部门,一切群策群力,解决耗时高的问题。
上图耗时监控图中蓝色箭头处,就是做了以上动作后,耗时未降,反而升高。按正常来说,以上动作绝对是有明显的性能提升的。这里我们思考一下?
图上所示,REDO每秒23M/S,TPS每秒3415,CPU 160,物理内存1TB,等待事件log file sync确实是没了。但是凸显的是db file sequential read。很奇怪哈,因为这套库本人特别了解,历经三代,由早的REDO 512M2 MEMBER10历经六年优化到现在,一直致力于解决commit过多的问题,目前log file sync没了,出来的是顺序读,这里有什么不同点呢?回顾迁移时候,库的不一样,发现我们有一些幂等表,由迁库前的周分区表,变至日分区。而我们的分区,都是一年维护一年半的分区,举个例子。
yjf.partition分区表 P20230308 values less then (20230308)..... P20240808 values less then (20240808)...PMAX
这里的区别就是我们的分区数量由周一年+的分区数416个月分区数量=64个分区数量,变成了日分区一年+的分区数30*16=480个分区数量。这里需要注意幂等表在我们的生产环境中数量是做了水平拆分的,数量可观,所以,周边日,是一个外因素。而该数据库系统,也从此前仅有的log file sync变成了db file sequential read。
从400GB大表count速度来看,我们的新库新存储上的性能有明显的效果,老库需要7min、新库是它的一半时间。这里时间节点先做定格。
阶段二:有一些跑批流程上的耗时明显增加(尤其是重大节假日)如下是在春节左右的一段优化工作,从一个DBTIME的告警开始的~
我们的跑批任务是一个小时一次,做一些资金的sum运算,在这个跑批任务里面,包含多种运算逻辑。那么在无法击破单个SQL带来的影响外,我们只能从SQL整体逻辑下手,对比不同。
如下是基于以上的优化后的一些效果,如跑批SQL前后耗时比对--来自AWR报告
阶段三:刨根问底协同开发继续深化优化可能怀疑的方向
在PLSQL中分别执行了未加时间裁剪的跑批SQL,虽然是走了执行计划,但是还是partition range all
而我们添加了时间字段后,执行计划有了变化,执行时间也有体会(因业务逻辑,不能准确判断是哪一天,故使用between and)
开发大佬反馈说,在查询书写方式一模一样的情况下,只是商户的值不一样。为什么会有查询效率的变化呢?这里其实可以使用10046去追踪一下看看哪里不同。
索引分裂的解决思路,我们的索引分裂,是91,还是55呢?这个问题,相信很多的DBA或者开发无法回答,如果不了解生成业务系统以及逻辑的话,我们从AWR里面可以清楚的获得
55分裂的发生一般跟表插入的值比较随机,不是按照递增的去插,比较随机。
91分裂的发生主要发生在序列字段,自增字段。
leaf node 50-50 splits 当插入到索引叶子块中的索引键值不是该块中的最大值时(包括块中已删除的索引键值), 将发生 50/50 split分裂, 这意味着有一半索引记录仍存在当前块,而另一半数据移动到新的叶子块中。
从AWR里面,我们可以清楚的看到是IDX1和IDX4争用严重、同时在生产上,会有ITL事务槽的等待,那这就简单了,我们生产规范这种大表的PCTFREE是默认上线在初始化参数上是调整到20的。
因为任何关于底层的改动,都会有真实的场景,真实的数据,切不可急挠挠的就去做改动,在压测环境进行压测后得出如下结论
目前该问题暴露的不是很严重,还在多场景压测中,看下在批提的同时,多大的itl槽位可以满足我们业务量翻倍的要求。
阶段四:万法归宗,各类组合拳下的优化成效