`
moss
  • 浏览: 7587 次
文章分类
社区版块
存档分类
最新评论

窥豹一斑:系统设计对系统运行性能的影响

 
阅读更多

1背景

业务背景

   某企业现有一应用系统运行该企业业务审批流程,审批流程有6个;

数据量

  系统运行3年,拥有业务数据20万余条;

问题描述

  查询审批流程时间大约15秒,此查询速度对用户来说无法接受,按行业标准查询速度应该在5秒内,5秒是用户接受响应速度的最大值。

运行环境

表一客户端运行环境

序号

项目

参数

备注

1

cpu

intel奔腾2.39G

 

2

内存

2G

 

4

操作系统

window xp

 

5

浏览器

ie8

 

客户端计算机的配置比较低,一般都是4年前的计算机

 

表二应用系统运行环境

序号

项目

参数

备注

1

数据库

oracle 11g

 

2

数据库运行环境

unix

 

4

应用系统开发平台

java

 

5

web服务器

tomcat6

最大内存配置2G

6

web服务器运行环境

Linux

 

7

系统并发数量

50人左右

 

应用系统运行的服务环境良好

 

2分析

问题定位

应用系统在设计之初选定了JQGrid组件用于展示数据,针对考虑到客户端性能问题,焦点首先集中在此组件上,觉得是此组件在渲染数据时让查询数据变慢,为了验证这一猜想,使用了HttpWatch工具进行分析,分析数据如下面表格:

表三 httpwatch监测数据报告

序号

分析内容

持续时间()

备注

1

加载jscss、图片等内容

0.7

 

2

从数据库中取数据

13.5

 

3

js渲染加载数据

1.1

 

合计

15.3

 

分析的数据让我们大跌眼镜,本来以为是JQGrid性能问题,结果是数据这个层级出了性能问题。定位到了问题,我们接下来对设计进行多个维度分析。

 

问题分析

  • 业务

    系统运行了6种类型的审批流程,在查询界面需要查看申请单号、申请时间、申请人、申请部门、当前状态、用途、申请类型信息,6种类型的申请单中有5种申请单含有以上所有需要查看的信息,还有1种申请单不具备用途这一信息。

  • 程序设计

软件设计人员对此业务进行分析后进行了如下实体类设计:

  • 1个基类:命名为Apply,此类含有申请人、申请部门、申请时间、当前状态、申请类型属性;

  • 5个流程类:继承基类Apply,流程类含有业务属性;

  • 1个流程类:继承基类Apply,流程类含有用途属性与业务属性

从面向对象的程序设计上来看此种设计不存在任何瑕疵。

  • 数据库设计

    根据实体类设计,创建了6张业务表来存储业务数据:1张基表,6张业务表,基表的数据字段如下表:

 

表四:基表[1]

序号

字段名称

说明

备注

1

id

系统标识

主键

2

code

申请单号

 

3

deptId

申请部门id

 

4

userId

申请人id

 

5

state

状态

 

6

time

申请时间

 

7

type

申请单类型

 

表名:t_apply

 

表五 业务流程表[2-6](含有用途属性,5张表)

序号

字段名称

说明

备注

1

id

系统标识

主键,值与基表中的id值一样

2

purpose

用途

字符类型,最多100个字符

3

xxx

业务属性1

 

n

……

业务属性n

 

表名:t_apply_1 t_apply_55张表)

 

表六 业务流程表[7](不含有用途属性)

序号

字段名称

说明

备注

1

id

系统标识

主键,值与基表中的id值一样

2

xxx

业务属性1

 

n

……

业务属性n

 

表名:t_apply_6

 

序号

数据表

表名称

数据量()

备注

1

申请基表

t_apply

280,000

 

2

申请业务表一

t_apply_1

160,000

含目的字段

3

申请业务表二

t_apply_2

10,000

含目的字段

4

申请业务表三

t_apply_3

20,000

含目的字段

5

申请业务表四

t_apply_4

15,000

含目的字段

6

申请业务表五

t_apply_5

30,000

含目的字段

7

申请业务表六

t_apply_6

 45,000

不含目的字段

 

  • 应用系统层

应用系统在查询申请单时,每页显示100条数据,开发人员使用以下设计方案查询申请数据:

1 查询申请主表t_apply;

2 根据主表的id值分别查询6张子表,从子表中获取purpose字段值,并在页面显示;

根据上面设计方案,查询100条申请数据最少需要执行1+100=101次查询,最多需要1+100*6=601次数据库查询,平均查询次数为(101+601)/2=351,分析得出查询数据缓慢的原因。

 

3解决方案

经过对问题的分析,我们知道了问题所在的原因,根据当前面向对象的设计观点及数据库三范式的设计原则,此设计是满足标准设计原则的。为何满足了业务需求与设计需求,但是还是会出现以上问题,这值得我们设计人员及开发人员思索这个问题,此问题集中的焦点在查询条件中含“目的”信息,为了实现这一查询目标,在现行的设计框架下必须牺牲系统性能,为此我们能否折中处理,下面提出3种解决方案(其实方案还有更多,办法总比问题多)。

3.1方案1

改进目标

  • 工期最短;

  • 不改变原有系统结构,系统调整最少;

  • 缩短一半查询速度;

 

改进方案

  • 创建目的视图,将t_apply_1t_apply_5 union连接为一张视图:

CREATE OR REPLACE VIEW t_apply_purpose_viewAS

SELECTid,purpose FROM t_apply_1

UNION

SELECTid,purpose FROM t_apply_2

UNION

SELECTid,purpose FROM t_apply_3

UNION

SELECTid,purpose FROM t_apply_4

UNION

SELECTid,purpose FROM t_apply_5

  • 创建带有“目的”的申请单视图

CREATE OR REPLACE VIEW t_apply_view AS

SELECT a.*,b.purpose FROM t_apply a

LEFT OUTER JOIN t_apply_purpose_view b ona.id = b.id

  •  修改应用系统代码

将以前的SQL语句中查询的表替换为t_apply_view

 

改进耗时

半天时间

 

改进效果

序号

分析内容

持续时间()

备注

1

加载jscss、图片等内容

0.7

 

2

从数据库中取数据

6.2

 

3

js渲染加载数据

1.1

 

合计

8

 

3.2方案2

改进目标

  • 工期适中;

  • 系统调整适中;

  • 查询速度缩短到5秒内;

 

改进方案

  • 在申请基表t_apply中增加purpose字段;

  • 每次在不同申请单中申请时自动将purpose值写入申请基表中,修改每个申请单申请结果;

  •  查询时直接查询t_apply中数据,一条SQL语句执行即可;

 

改进耗时

5天时间

 

改进效果

序号

分析内容

持续时间()

备注

1

加载jscss、图片等内容

0.7

 

2

从数据库中取数据

2

 

3

js渲染加载数据

1.1

 

合计

3.8

 

在此方案中查询速度得到了大大提升,是一个近似完美的方案。如果客户给定的资金支持是一个定值,我们架构师是否会考虑时间成本问题,此方案是否是一个最优解?我们架构师能否再仔细的考虑一下,能否实现双方共赢的局面:客户资金耗费少,改造时间成本低?在此问题上,我们引入下面的方案3

 

3.3方案3

改进目标

  • 工期适中;

  • 系统调整适中;

  • 查询速度缩短到5秒内;

 

改进方案

  • 在申请基表t_apply中增加purpose字段,并创建索引

  • 创建目的视图,将t_apply_1t_apply_5 union连接为一张视图:

CREATE OR REPLACE VIEW t_apply_purpose_viewAS

SELECTid,purpose FROM t_apply_1

UNION

SELECTid,purpose FROM t_apply_2

UNION

SELECTid,purpose FROM t_apply_3

UNION

SELECTid,purpose FROM t_apply_4

UNION

SELECTid,purpose FROM t_apply_5

  • 初次使用前利用t_apply_purpose_view视图更新t_applypurpsose字段;

  • 在每次查询的时候更新t_apply表中的purpose字段为空的记录,

UPDATE t_apply a SET

   purpose = (SELECTpurpose FROM t_apply_purpose_view WHERE a.id=b.id)

WHERE a. purpose IS NULL

  • 直接查询t_apply数据,2SQL执行即可;

 

改进耗时

1天时间

改进效果

序号

分析内容

持续时间()

备注

1

加载jscss、图片等内容

0.7

 

2

从数据库中取数据

2.8

 

3

js渲染加载数据

1.1

 

合计

4.6

 

在此方案中查询速度得到了大大提升,是一个近似完美的方案。如果客户给定的资金支持是一个定值,我们架构师是否会考虑时间成本问题,此方案是否是一个最优解?我们架构师能否再仔细的考虑一下,能否实现双方共赢的局面:客户资金耗费少,改造时间成本低?在此问题上,我们引入下面的方案3

 

3.4 方案效果对比

 

序号

客户需求

方案名称

工时(天)

改进后查询速度(秒)

提高百分比

改进前查询速度(秒)

1

工期短;查询速度缩短到原来的一半

方案1

0.5

8

47.7%

15.3

2

工期适中;查询速度降低到5秒内

方案2

1

3.8

75.1%

3

方案3

5

4.6

69.9%

 

4问题分析

我们追根索源这一问题,对当时的情景进行还原再现,想对应的人员请大家看看如果我们是场景中的人,我们是否也是这样来做的,请做个对照。

被访谈人员(甲方):

我们现在有一批申请业务希望电子化,该审批业务涉及到6种不同的申请。

访谈人员(乙方):

您有6种不同类型的申请,请您提供一下6种纸质版本的申请表格,最好已经有了数据的纸质表格,数据可以供我们参考一下,另外给我们提供一份电子表格。请问你们会根据什么样的条件去查询这些申请表?

被访谈人员(甲方):

       我们想根据申请时间、部门、人员工号、人员姓名、申请单类型来查询,这些条件基本够了,我们需要在查询列表上显示在查询界面需要查看申请单号、申请时间、申请人、申请部门、当前状态、用途、申请类型信息。

甲方找来已经存档的纸质申请单交给乙方,各种申请单提供了10多份。

访谈人员(乙方):

       您能详细描述一下各种申请业务流程是如何审批的吗?

被访谈人员(甲方):

我给你把每种业务解释一下,便于你们能够理解。

甲方将审批流程业务详细的讲解给乙方,直到乙方完全理解各个流程的审批过程,双方的焦点集中在审批流程上。乙方将资料带回单位对业务进行梳理分析,并画出泳道图给客户确认,客户拿到泳道图,对着单位的相关制度进行逐一确认。

       乙方根据甲方所提的需求进行设计、开发、测试、上线,在系统运行的第一年里没有什么问题,在第二年里速度会有些慢但是不太明显,到了第三年限系统运行速度缓慢问题就凸显出来,于是便有了上面一幕。我们回过头来看看,从专业的角度看看我们调研的时候所问的问题是否有所欠缺:

  • 我们是否对系统数据量有个预估;

  • 我们在设计的时候是否真的吃透了用户的需求;

  • 我们是否了解客户潜在的需求;

访谈人员在访谈前制定调研提纲,提纲如下:

  • 组织架构是什么样的?

  • 系统使用人员的人数?

  • 每天业务数据有多少?

  • 所需系统响应时间为几秒?

  • 客户使用计算机是什么样配置?

  • 服务器配置是什么样配置?

  • 。。。。。。。。。。。。。。。。。。。。。。。。。。

(后面我们将会制作一篇如何做好调研的文章)

根据提纲询问得到的答案,制定架构设计原则:

  • 客户端硬件配置决定了系统开发使用的前端框架;

  • 系统使用人数*每天业务量*12=一年业务数据流

设计人员在获取客户需求、系统反应时间、业务数据量的情况下进行设计,回到审批流程查询这一特定问题上,在申请主表上加入“目的”冗余字段,在每个申请提交的时候将“目的”信息写入申请主表中。此种方案正是方案2的设计思路。

 

5总结

一个小小的设计导致了系统运行缓慢,设计人员要从中吸取一定的经验教训,自己挖下的坑,一定是需要自己或队友去填坑的(不怕复杂的系统,只怕猪一样的队友),出来混迟早是要还的。

       造成这一问题原因是在需求及设计阶段未全面分析导致的,在应用级别的系统中低层数据库结构设计是非常重要的,数据库结构设计决定了上层应用开发的复杂度及系统运行的效率,在后面的文章中,我们将会介绍几种典型业务对应的数据库设计知识,敬请期待。

 

6后续

如果您喜欢我们的文章或者有什么好的意见,请订阅我们的微信公众号并给我们留言,我们是一个专注业务及业务技术实现的团队。

 

微信公众号:构建设计编程



 

 

  • 大小: 38.1 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics