关于医药采购系统性能优化的设计与实现

2015-07-18 13:43:15闫涛朱希安
电脑知识与技术 2015年12期

闫涛++朱希安

摘要: 医药采购系统的用户数量很多,每个用户每年采购的药品数量庞大。数据库存储的数据过多会极大的影响系统的性能,查询的速率会降低。为了提升系统的性能,该文从数据聚合、动态建表,按年存储这两个角度进行了设计与实现。从而提升了系统的查询速率、系统的性能得到了优化。

关键词:数据聚合;动态建表;按年存储

中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2015)09-0263-02

医药系统的业务用户有市卫生局、镇卫生院、村卫生室、供货商。涉及到的采购单位是一个市下属的各个村卫生室、社区医院。一个大的市下属的村和社区大概有个3000左右。一个采购单位每月分上中下旬采购药品,每次保守采购100个药品。一年采购量:3000*100*3*12=10800000,一年下来采购量估计在千万级。系统上线后,运行几年后会存储量很大。存储随着年复一年,日复一日,存储量会非常大。 为此我们选用了Oracle数据库,Oracle 是海量存储的数据库,比Mysql要强很多,Mysql最多存储量大概是二百万左右,如果再多就超出它的能力范围。所以,我们使用Oracle海量存储。Oracle海量存储可以存很多,但是,如果存储很多,我们要做一些查询、统计分析,查询的效率很低,系统反应很慢。

我们可以对表进行一些优化,比如说:加一些索引,我们可以使用Oracle的一些分区表,可以做一些sql语句的优化。但是,这些都是治标不治本的。治本的解决需要待查询的表存储的数据少,我们现在需要对系统进行一个根本的解决。

1 解决方案的设计与实现

本文主要从数据聚合、动态建表,按年存储这两个角度对系统的性能进行优化。数据聚合针对系统的统计分析功能模块进行的设计;动态建表、按年存储涉及到系统的核心功能模块--采购单模块,对系统采购单模块相关的表进行存储,全部是按年存储。

1.1 数据聚合

1.1.1问题的提出

采购系统有个功能模块是统计分析。系统有市卫生局、卫生院、卫生室、供货商四个业务用户。市卫生局查询本市所有医院及供货商的交易明细,卫生室查询本地区所有医院与供货商的交易明细,医院查询本医院的交易明细,供货商查询与自己供货相关的交易明细。

根据用户的需求,统计分析模块中按交易明细的统计效果图2所示:

从图中我们可以看出明细查询涉及到:采购单明细、入库信息、退货信息、结算信息。采购单明细是必须显示出来,入库信息有则显示没有不显示,退货信息有则显示没有不显示,结算信息有则显示没有不显示。

1.1.2 一般的解决思路及存在问题

思路:采用采购单明细表分别和入库表、退货表、结算表左连接查询。

存在问题:采购单明细一年下来上百万,入库表也是上百万,退货表少,结算表上百万数据大,进行关联查询速度很慢。

1.1.3 采用数据聚合进行优化

将采购单明细、入库信息、退货信息、结算信息的数据融合到一张表里,这时去查询速度很快,不用进行关联查询。创建一张表:YYBUSINESS,此表汇集了那几张表所有的字段.

同步数据时机:

对于采购单明细数据,采购单审核通过后开始向交易明细表(yybusiness)插入数据。将该采购单下的采购药品信息插入yybusiness表。由于有业务逻辑采购单审核通过,所以采用service层修改代码实现数据同步。

对于入库信息、退货信息、结算信息这三张表数据采用采用触发器实现数据同步。

入库表上建立的触发器源代码如下:

create or replace trigger yycgdrk2014_insert after insert on yycgdrk2014 for each row

declare begin update Yybusiness2014 t set t.rkl = :new.rkl,t.rkje = :new.rkje,t.ypph = :new.ypph,t.cgzt = :new.cgzt,t.rkdh = :new.rkdh,t.ypyxq = :new.ypyxq,t.rktime = :new.rktime where t.yycgdid = :new.yycgdid and t.ypxxid = :new.ypxxid; end yycgdrk2014_insert;

这样,本系统将药品的采购信息、入库信息、退货信息、结算信息全部聚合在一张交易明细表中,统计分析时在该表(交易明细表)上进行统计分析。由原来的多表关联改为单表查询,速度提升。

1.2 动态建表,按年存储

1.2.1 动态建表

动态建表是创建定时任务,由定时任务去执行存储过程。由存储过程自动创建所有用到业务表(动态表)及与表相关的触发器、外键、索引、序列。如果让人去创建,显然是不合理,时机也不好把握。

创建定时任务的三种方法:1)java 程序启动一个定时任务;2)数据库上建立一个定时任务;3)在操作系统上创建一个定时任务。

本系统采用第三种方法去创建定时任务。创建的定时任务,是到点去执行Oracle.bat文件。Bat文件的内容是连接到数据库,执行sql。Bat文件内容是:

sqlplus yycg0406/yycg0406_192.168.56.101 @c:\test.sql。test.sql的内容是执行存储过程。具体内容是:call create_tableJob();

create_tableJob的原代码如下:

create or replace procedure create_tableJob Authid Current_User as

year1 varchar2(4);

year2 varchar2(4);

begin

select to_char(sysdate,'yyyy')into year1 from dual;

select to_char(to_char(sysdate,'yyyy')+1)into year2 from dual;

create_businesstable(year1);

create_businesstable(year2);

end create_tableJob;

create or replace procedure create_businesstable(year in varchar2) Authid Current_User as

begin

create_business(year);

create_businesscgd(year);

create_businesscgdmx(year);

create_businesscgdrk(year);

create_businessthd(year);

create_businessthdmx(year);

create_businessjsd(year);

create_businessjsdmx(year);

end create_businesstable;

1.2.2按年存储

动态分表的策略一定是根据用户的需求决定。因为用户查询采购单的统计信息,一般都是按年进行查询的。没有动态分表,系统就是一个表。按年存储采购单后面加年份。年份是4位。例如:yycgd2014,yycgdmx2014。如果是按年存储,需要对自动生成的mapper.xml

进行修改。例如:Yycgd变成yycgd${businessyear},通过mapper中的传入参数扩充businessyear字段来实现。扩充后,可以将参数传入mapper中的sql语句中。

具体操作步骤:

1)按照原来生成规则生成mapper及po类,是根据模版表生成.

2)修改mapper.xml文件中的内容

将表名后边加:${businessyear}

3)修改生成的po类,XXX Example类

继承BusinessBasePo类

BusinessBasePo类扩充businessyear字段。

2 结束语

本文针对开发的医药采购系统中存在的大数量存储的问题导致的系统查询效率低下问题,从数据聚合、动态建表,按年存储角度进行了设计与实现。数据聚合解决了多表关联从而导致的查询慢的问题。将数据聚合到一张表上,从一张表查询统计的数据。动态建表是由定时任务定时去创建相关的表。采购的相关信息按年进行了存储。从而用户从页面查询时选择查询的年份,查询出相关年份的信息。这样解决了查询效率低下的问题。从一定程度上对系统的性能进行了优化。

参考文献:

[1] 阎冰洁, 万亮, 肖敏. 高性能查询分页技术的研究与应用[J]. 电脑知识与技术, 2006(14): 74.

[2] 王焜, 李翠华. 基于J2EE的高校教学管理系统的性能优化设计[J]. 计算机与现代化, 2008(11): 134.

[3] 武志鹏. web服务的性能优化研[D]. 厦门: 厦门大学, 2007.

[4] 魏璞. web优化的研究及其应用[D].北京: 北京邮电大学, 2008.