找回密码
 立即注册

QQ登录

只需一步,快速开始

Carl

版主

49

主题

213

帖子

962

积分

版主

Rank: 7Rank: 7Rank: 7

积分
962

活字格认证微信认证勋章

QQ
Carl
版主   /  发表于:2009-12-10 13:37  /   查看:7159  /  回复:0
Post by "GaryYou", 2007-05-10, 17:11
-----------------------------------------------------

  • 两重循环的性能问题
    • 问题
      在一个Grid上,有3万行数据需要被锁定,其中一部分数据有父子关系。一个父可以有多个子,但是一个子只能有1个父。当我们锁定一个父时,必须将所有的子也同时锁定。我们用parent来代表父行,用child来代表子行。其中,parent和child都有一个属性ItemID,而child有一个属性叫做ParentID,指向parent的ItemID。3万行数据中,有1万个父,1万个子。
    • 原始方案
      每拿到一个父,通过循环,找到它的每一个子,同时锁定找到的子。

      代码:
      1. For each parent as row in parents

      2.   For each child as row in children

      3.      If child.parentid=parent.itemid

      4.          ‘进行子的锁定操作

      5.      End if

      6.   Next

      7. Next
      复制代码
      那么,以上循环的执行次数为:1万*1万=1亿,执行时间可能需要1分钟左右。
    • 优化方案
      不通过父找子,而是通过子找父,查找的时候也不用循环来查找,而是通过datatable的find方法进行查找。实现步骤如下:

      首先,创建包含所有父的datatable,该表以ItemID为主键
      1. For each parent as row in parents

      2.     parentTable.AddRow(row)

      3. Next
      复制代码
      然后,进行子找父的操作。
      1. For each child as row in children

      2.    If not parentTable.rows.find(child.parentid) is nothing

      3.       ‘子找到了父,进行子的锁定操作

      4.    End if

      5. Next
      复制代码
      由于DataTable的Find方法执行的高效,通过上述的方式,最终执行时间控制在5秒以内。
    • 结论
      使用DataTable的Find方法,有时可以解决多重循环的性能问题。
  • 关于C1FlexGrid的大数据量行的删除。
    • 问题
      在C1FlexGrid,有3万行数据需要被删除,但是这3万行数据不是连续的。
    • 原始方案
      1. For each row as C1FlexGridRow in deletedRows

      2.     Grid.rows.remove(row.Index)

      3. Next
      复制代码
      需要时间2分钟
    • 优化方案
      先记录要删除行的index
      1. For each row as C1FlexGridRow in deletedRows

      2.     deleteIndexs.add(row.Index)

      3. Next
      复制代码
      再从后往前删除行
      1. For I as integer =deleteIndexs.count-1 to 0 step -1

      2.     Grid.rows.remove(deleteIndexs(i))

      3. Next
      复制代码
      执行时间,5秒以内
    • 总结
      C1FlexGridRow的Index属性,要小心使用。如果有行被删除,然后再使用该属性,其值可能需要进行集合的遍历才能得出,所以会有性能问题。
  • 关于类型转换的问题
    • 背景
      有一个class名叫RejectItem,它有一个属性叫RejectDate
    • 原始代码
      1. ‘ rejectList为ArrayList

      2. If rejectList(i).rejectDate>”#1/1/2006#”

      3.    ‘ 内部操作

      4. End if
      复制代码
    • 优化代码
      1. If Ctype(rejectList(i),RejectItem).RejectDate>”#1/1/2006#”

      2.      ‘ 内部操作

      3. End if
      复制代码
      使用该方式,性能可以提高一个数量级。
    • 总结
      Object对象,通过“object.xxx”的方式使用其属性或方法,即使属性方法不存在,编译的时候也不会出错,只是运行时会出错。如果使用的属性或方法存在,那么通过这种方法使用,虽然不会出错但是其运行效率会大大降低。
  • 灵活运用表约束检查
    • 背景
      1件资产,存入数据库,需要用到11个表。其中一个表为基本信息表,其余表都和它有外键约束关系。

      现在,我们要向系统录入大数据量的资产信息,比如1万件资产。那么,相应的,我们就要录入数据库记录几十万行。
    • 原始方案
      按照普通模式,一条资产一条资产的往数据库写入,每写一条资产信息,都要进行数据库外键约束的检查。这样的方式,执行速度较慢。
    • 优化方案
      将1万件资产分批,比如100件资产一批,一批资产进行一回录入操作。

      每一批资产数据,首先通过CODE验证的方式,检查有外键约束的字段是否合法,然后才进行数据插入。

      在插入数据之前,通过“NOCHECK”语句,关闭相关资产表的外键约束检查;

      然后再插入资产信息;最后通过“CHECK”语句,再打开相关资产表的外键约束检查。

      通过以上的操作方式,可让资产信息的录入速度提高5倍左右。
    • 总结
      外键约束输入可以保证录入数据的完整性,但是却牺牲了录入性能。对于大数据量的数据录入,这个外键约束将会极大的降低性能。

      我们可以通过CODE验证的方式,保证传入数据的外键约束完整性,而不是使用数据库自身的外键约束机制来进行检查。
  • 高效使用系统设置信息
    • 背景
      资产在作减价尝却的时候,需要得到一个尝却率信息列表,对应于数据库中的上百行记录。
    • 原始方案
      有一个接口,返回的就是尝却率信息,不过内部通过数据库查询实现。

      如果有1000个资产,每个资产都需要进行减价尝却,为了获得尝却率信息,那么就要进行1000次的数据库查询。
    • 优化方案
      取一次尝却率信息,然后进行将其作为全局变量暂存或是作为参数传递给需要的方法。1000件资产,只需1次尝却率信息的数据库查询。
    • 总结
      对于数据的批量处理,如果需要用到系统设置信息,必须做到一批数据取一次设置信息,而不是每条数据都去取一次设置信息。

0 个回复

您需要登录后才可以回帖 登录 | 立即注册
返回顶部