杨久莉,石国玲,段季芳
(合肥京东方光电科技有限公司 自动化技术部,合肥 233100)
基于MES系统业务逻辑的性能优化
杨久莉,石国玲,段季芳
(合肥京东方光电科技有限公司 自动化技术部,合肥 233100)
MES是面向制造企业车间执行层的生产信息化管理系统,在系统初期由于数据量小、系统压力轻,其系统的缺点不易暴露出来。随着时间的推移,各种问题都会出现。在性能调优的方法中最常用的方法是SQL调优,但是有的SQL已经是最优,只能通过修改业务逻辑来实现调优的目的。本文列举几个比较经典的案例,以期为MES系统开发和维护人员提供帮助。
MES系统;业务逻辑;性能;优化
MES系统的性能直接关系到工厂一线的生产,性能低下的系统功能会直接影响到工厂的生产进度,从而间接影响到产能。因此,高效的业务执行在MES系统中至关重要,在生产总数据量庞大、单位时间内业务处理量高的繁忙系统中更加明显。本文将结合生产制造行业的MES系统特征,以实际业务系统中出现的业务查询和更新时性能问题作为出发点,结合业务逻辑,有效地实现了业务处理性能的改善。
应用的SQL性能一般通过AWR报告来分析,出现报告中Top SQL上的语句一般需要进行性能分析。通过观察AWR发现有两条查询占用33.7%的DB Time,其SQL是用来查询系统表的数据,且使用者是用户。
经分析,这两条SQL是应用使用SimpleJdbcCall调用存储过程或者函数产生的。SimpleJdbcCall是一个多线程、可重用,用来调用存储过程或者函数的工具,它通过提供元数据的处理方式来简化对基本存储过程和函数的访问。在执行存储过程或者函数时,只需要提供执行存储过程或函数的名字和用Map表示的相应的参数,这些参数的名字将会与创建存储过程或者函数时定义的参数名进行匹配。
这种方式为应用程序开发者简化了代码,但是对于存储过程或者函数使用较多的系统,则会出现资源争用的情况。SimpleJdbcCall提供的addDeclaredParameter方法来指定每个变量的类型,就可以避免SimpleJdbcCall在执行存储过程或者函数时先调用元数据的过程。因此,将应用上所有的函数中增加了addDeclaredParameter这个方法,完成优化后不但提高业务的处理速度,也降低对DB资源的争用情况,两个查询从Top SQL中消失。
笔者观察AWR发现有一条SQL,它的平均执行时间为0.2s,占了接近1.73%的DB Time,但是对应表是一个20M的小表,这样的查询出现在Top SQL中绝对是有问题的。分析其执行计划,CBO选择IDX_01,Cost数值为653。
对数据及查询结果进行分析,此表总数据约为24万条,此查询的结果返回13条基准信息。IDX_01索引列名为(FACTORYNAME),而整张表中此列值相同,没有任何选择度;其次,此表还有一个基于(SUPERAREANAME)列的索引IDX_02,而要查询出来的数据所对应的SUPERAREANAME为NULL值。即使在Where条件上SUPERAREANAME的筛选条件,基于以上数据分布和Oracle的特性,该CBO不会选择IDX_02。综合业务分析,最终将这13条数据的SUPERAREANAME列填写具有区分度的数据,并将此列加到Where条件中。再次分析执行计划,Cost数值由652降低为2。再次查看AWR,此条SQL从Top SQL中消失了。
以上案例可以看到,对单表进行查询优化时,先对数据和现有的Index进行分析,有时候不需要建立额外的Index,而是对数据稍作变动,就能解决问题。由于B*Tree索引不存储Null值,所以查询NULL值数据时,Oracle会因为Null值的存在而放弃索引。为了此种情况发生,使用默认值代替NULL值,或者在建立index时使用联合索引而非独立索引。
用户一直反映某个查询较慢,经常因为查询时间较长而收到超时错误。分析此查询的SQL语句,语句并不复杂,当前使用的索引也是最优的。通过tkprof工具对Trace文件进行分析,发现SQL执行的主要时间是花费在数据获取(fetch)上,total数据为:disk (51163)、query(76985)、current(0)、rows(1764),平均每行所需的block数=(query+current)/rows,此查询平均读取每行需要的Block数约为44块。正常情况,访问一条数据的速度由索引的高度和回表查询的IO决定,一般索引高度都在3层以下,正常查询一条数据,IO在4个以内。即访问一条数据需要访问的数据块的个数不超过4个,本案例中达到44块,说明索引的扫描效率太低,或者说该索引不合适该查询。经过数据分析发现,需要查询的数据只占整个表的小部分,总共73 639行数据,且分布在67 041个数据块中,因此考虑根据数据状态,将大表拆分,如果再建立合适的索引,查询效率就会非常的高。
此表由一个工厂和库房共用,数据量为61Gb、数据为79 934 965行,数量巨大。如果直接在原表中建立一个十列信息的联合索引,则会占用12G左右的空间。如果将工厂和库房的数据分开,则需要停线。经过综合分析考虑,将此表中车间数据放到一张单独的表中,并在上面建立全部数据的Index。
更改后,再次分析Trace中的执行计划,得到total数据为:disk (0)、query(1757)、current(0)、rows(1784)从磁盘上的数据文件中物理读取的块的数量由51 163个降低为0个,平均读取每行需要的Block数也降低到1块,实际执行时间也由将查询速度由原来首次执行的2分32秒减少到781毫秒。
发货在FGMS中一直是比较慢的操作,由于需要处理的数据比较多,处理速度一直很慢。SQL已经是最优,应用处理方式由API改为存储过程,更新方式也改为最快的BULK处理方式,但是在遇到数据量大的发货单,仍然需要很长时间。发货数量超过30W的发货单,由于处理时间超过TimeOut(20分钟)的时间,应用直接报错。每到月底发货量大的时候,用户体验更差。在AWR的TOP SQL中,此业务在15分钟内执行11次,平均时间约81 s,占整个DB Time的5.43%。
此存储过程里设计的查询语句及更新方式都是最佳方式,业务的逻辑处理方式也经过了很多次的优化。除了提高硬件性能外,如果保持现有逻辑已经没有其他提高处理速度的方法。发货时,用户只关注发货单及Pallet的信息变化情况,不会观察Panel的信息情况,故采用了异步处理的方式,先更新Pallet数据及发货单信息并将结果反馈给用户,在用另一个进程更新Panel信息。
此方法只适用于对部分数据更新实时性要求不高、且异步执行部分都保证更新成功的情况,否则会造成数据不一致,影响后续业务的处理。
一个系统要稳定地、高效地运行,离不开持之以恒的系统调优。调优的方法中SQL优化是最直接、最方便,见效最显著的,但并非所有的问题都是能通过SQL调优来解决的。当SQL已经没有优化空间时,不妨对业务逻辑或者业务数据进行变动,来达到系统优化的目的。从传统的“供给”改为“供需”,节约资源,降低投入。
主要参考文献
[1]陈冠星.企业应用开发中Oracle的SQL优化[J].软件导刊,2014(12).
[2]罗时飞.精通Spring——深入Java EE开发核心技术[M].北京:电子工业出版社,2008.
[3]陈雍,谢旭升,魏根芽.Oracle B*树索引内部机制及其应用的研究[J].计算机与现代化,2008(10).
[4]谭怀远.让Oracle跑得更快——Oracle 10g性能分析与优化思路[M].北京:电子工业出版社,2010.
10.3969/j.issn.1673 - 0194.2016.16.039
TP311.52
A
1673-0194(2016)16-0059-02
2016-07-08