[转帖]介绍一些用于提高数据窗口性能的技术
1. 减少连接数据库的次数 <br/>连库操作是非常影响执行速度的操作. 因此在程序中,一旦与数据库连接后就应当尽量保持与数据库的连接, 减少连接数据库的次数.PowerBuilder 提供里两个函数来建立数据窗口与事务对象的连接: <br/> SetTrans() <br/> SetTransObject() <br/>在程序中应当尽量使用 SETTRANSOBJECT(), 因为SETTRANS() 函数在每次调用 RETRIEVE(), UPDATE() 等函数之后, 都要执行数据库的连接和断开操作. <br/>2. 下拉数据窗口与表的连接 <br/> 对于数据库服务器来说, 表的连接操作是一项非常大的开销, 而 POWERBUILDER 提供的下拉数据窗口在某些情况下可以代替表的连接操作.例如, 为了在数据窗口上显示用户的电话号码和姓名:如果用表的连接的方法, 数据窗口对应的 SQL 语句应是这样的: <br/> SELECT "DA_DH"."DHHM", <br/> "DA_HTH"."DWM" <br/> FROM "DA_HTH", <br/> "DA_DH" <br/> WHERE ("DA_HTH"."DHHM"="DA_DH"."DHHM") <br/>同样的程序可用下拉数据窗口来完成, 这里不再具体介绍.但是, 应当注意, 以上两种方法究竟哪一种数据更快, 与表的结构, 表的数量, 连接的方法等均有关系, 应当具体分析. <br/>3. 共享数据 <br/>在一个应用程序中, 某些数据需要频繁的使用, 如果在每次使用时都从数据库中进行检索, 则需占用大量的服务器资源和网络资源. 为了减少开销, 可以在客户端对这些数据只进行一次检索, 然后允许其它任务共享这些数据. <br/> 例如, 如果有两个数据窗口, 都需要从第三方表中检索出用户的电话号码, 且此列用下拉数据窗口给出. 如果每次都对电话号码进行检索, 则性能较低. 因此, 可以单独建立一个关于电话号码的数据窗口. 在每次打开窗口时, 首先将电话号码检索到此数据窗口中, 然后另外两个数据窗口中关于电话号码的下拉数据窗口可以共享此数据窗口中的数据. <br/>在窗口的 OPEN 事件中编写如下程序: <br/> dw_1.settransobject(sqlca) <br/> dw_2.settransobject(sqlca) <br/> dw_3.settransobject(sqlca) <br/> // 检索 dw_1 <br/> dw_1.retrieve() <br/> // 使 DW_2 的下拉数据窗口共享 DW_1 <br/> datawindowchild child1 <br/> dw_2.getchild( "dhhm ",child1) <br/> child1.settransobject(sqlca) <br/> dw_1.sharedata(child1) <br/> // 使 DW_2 的下拉数据窗口共享 DW_1 <br/> datawindowchild child2 <br/> dw_3.getchild( "dhhm ",child2) <br/> child2.settransobject(sqlca) <br/> dw_1.sharedata(child1) <br/> 使用这种方法, 避免了各个数据窗口间物理的拷贝数据, 因此减少了空间上的开销,提高了应用程序的综合性能. <br/>4. 数据窗口间数据的拷贝 <br/> 如果需要在数据窗口间共享数据, 应当尽量使用 SHAREDATA() 函数, 但是, SHAREDATA() 函数并不是物理地在数据窗口间拷贝数据, 如工在显示数据的同时, 还要对数据进行操作, 则需要进行数据的拷贝. <br/>例如, 要求将 DW_1 中选定的行拷贝到 DW_2 中: <br/> 在窗口的 OPEN 事件中编程: <br/> dw_1.settransobject(sqlca) <br/> dw_2.settransobject(sqlca) <br/> dw_1.retrieve() <br/> 在数据窗口 DW_1 的 ROWFOCUSCHANGED 事件中编写下列程序: <br/> long lr <br/> lr = dw_1.selectrow(0,false) <br/> lr = dw_1.getrow() <br/> lr = dw_1.selectrow(lr,true) <br/>要完成从 DW_1 到 DW_2 的拷贝工作, 有两种方法: <br/>第一种: <br/>在按钮 "拷贝" 的 CLICKED 事件中编程 <br/>long lr <br/>lr = dw_1.getselectedrow(0) <br/>dw_1.rowscopy(lr,lr,primary!,dw_2,100,primary!) <br/>执行程序, 利用 POWERBUILDER PROFILER 得出所需时间为 1.7034(百分之一秒) <br/>第二种: <br/>在按钮 "拷贝" 的 CLICKED 事件中编程 <br/>dw_2.object.data = da_1.object.data.selected <br/>执行程序, 利用 POWERBUILDER PROFILER 得出所需时间为 0.8062(百分之一秒) <br/>5. 数据窗口属性的访问和修改 <br/>A. 数据窗口属性的访问 <br/> 在程序中访问数据窗口的属性有下列几种方法: <br/> A1. 采用点表达式访问 <br/> A2. 应用多个独立的 DESCRIBE() 函数访问 <br/> A3. 只使用一个 DESCRIBE() 函数, 采用复合参数访问多个属性 <br/>上面三中方法, 通常第一种方法最慢, 第三种方法最快. <br/>例如: <br/> 在窗口的 OPEN 事件中 <br/> DW_1.SETTRANSOBJECT(SQLCA) <br/> DW_1.RETRIEVE() <br/>第一种方法: <br/>在检索按钮的 CLICKED 事件中编程. <br/> string dx, dy, dh, dw <br/> dx = dw_1.object.da_dh.x <br/> dy = dw_1.object.da_dh.y <br/> dx = dw_1.object.da_dh.height <br/> dy = dw_1.object.da_dh.width <br/> st_1.text =dx+","+dy+","+dh+","+dw <br/>第二种方法: <br/> string dx, dy, dh, dw <br/> dx=dw_1.describe("da_dh.x") <br/> dx=dw_1.describe("da_dh.y") <br/> dx=dw_1.describe("da_dh.height") <br/> dx=dw_1.describe("da_dh.width") <br/> st_1.text =dx+","+dy+","+dh+","+dw <br/>第三种方法: <br/> string dx, dy, dh, dw <br/> st_1.text=dw_1.describe("da_dh.x" +& <br/> "da_dh.y" +& <br/> "da_dh.height" +& <br/> "da_dh.width") <br/>实验证明, 第三种方法的速度是最快的. 但是程序的可读性最差. <br/>B. 数据窗口属性的修改 <br/>在程序中修改数据窗口的属性有下列几种方法: <br/> A1. 采用点表达式修改 <br/> A2. 应用多个独立的 MODIFY() 函数访问 <br/> A3. 只使用一个 MODIFY() 函数, 采用复合参数访问多个属性 <br/>上面三中方法, 通常第一种方法最慢, 第三种方法最快. <br/>例如: <br/> 在窗口的 OPEN 事件中 <br/> DW_1.SETTRANSOBJECT(SQLCA) <br/> DW_1.RETRIEVE() <br/>第一种方法: <br/>在检索按钮的 CLICKED 事件中编程. <br/> DW_1.SETREDRAW(FALSE) <br/> dw_1.object.da_dh.x = 18 <br/> dw_1.object.da_dh.y = 16 <br/> dw_1.object.da_dh.height = 100 <br/> dw_1.object.da_dh.width = 200 <br/> DW_1.setredraw(true) <br/> st_1.text =dx+","+dy+","+dh+","+dw <br/>第二种方法: <br/> DW_1.SETREDRAW(FALSE) <br/> dw_1.modify("da_dh.x = 18") <br/> dw_1.modify("da_dh.y = 16") <br/> dw_1.modify("da_dh.height = 100") <br/> dw_1.modify("da_dh.width = 200") <br/> dw_1.setredraw(true) <br/>第三种方法: <br/> dw_1.modify("da_dh.x=18" +& <br/> "da_dh.y=16" +& <br/> "da_dh.height=100" +& <br/> "da_dh.width=200") <br/>实验证明, 第三种方法的速度是最快的. 但是程序的可读性最差.注意, 在方法一和方法二中, 都使用的 setredraw() 函数以减少屏幕的重绘, 否则, 执行速度将严重下降. <br/>6. 数据窗口中数据的访问 <br/>在程序中, 经常会需要动态的修改数据窗口中的数据. 对此, PB 提供了多种方法, 各种方法在性能上会有一些差异. <br/>A. 数据窗口中数据的访问 <br/> 目的: 将数据窗口中的电话号码存放在一个数组中.请比较下面两中方法. <br/> 方法一: <br/> string da_dh[] <br/> long ll,i <br/> ll = dw_1.rowcount() <br/> for i = ll to 1 stet -1 <br/> da_dh = dw_1.getitemstring(i,"dhhm") <br/> next <br/> 方法二: <br/> string da_dh[] <br/> da_dh[] = dw_1.object.dhhm.current <br/>测试发现, 第二种方法比第一种方法快将近一倍. 数据量越大这种差异越明显. <br/>B. 数据窗口中数据的修改 <br/> 目的: 修改数据窗口中的电话号码列的值. <br/> 请比较下面两中方法. <br/> 方法一: <br/> dw_1.setitem(i,"dhhm",l_name) <br/> 方法二: <br/> dw_1.object.name = l_name <br/>测试发现, 第二种方法比第一种方法快将近一倍. 数据量越大这种差异越明显. <br/>7. 数据窗口事件对性能的影响 <br/>对于数据窗口控制中经常发生的事件, 应当尽量减少其中的程序代码. <br/>特别是如下事件: <br/> A. itemchanged <br/> b. editchanged <br/> c. itemfocuschanged <br/> d. pbm_dwnkey <br/> e. rowfocuschanged <br/> f. retrieverow <br/>在这些事件中的任何处理程序, 都会降低应用程序的处理速度. 所以应当尽量减少这些事件中的处理程序, 必要时, 可以考虑只将重要的代码放在这些事件中, 而将剩余的代码放在一个传递的事件中. <br/>例如,如果需要用到数据窗口的 ROWFOCUSCHANGED 事件,可以为数据窗口定义一用户事件 "UE_RE",而在数据窗口的 ROWFOCUSCHANGED 事件中写如下代码: <br/> PARENT.postevent("ue_re") <br/> 在 UE_RE 事件中再编写相应的程序代码,如: <br/> string code <br/> dw_1.selectrow(0,false) <br/> dw_1.selectrow(rownum,true) <br/> code = getitemstring(dw_1,rownum,"dhhm") <br/> dw_2.retrieve(code) <br/>另外, 为了获得当前行号,应尽量使用数据窗口的 CURRENTROW 变量,而少用 GETROW() 函数。 <br/>8、 数据窗口的列名称与列编号 <br/>对数据窗口的某列进行访问, 可以采用该列的名称, 也可以使用该列的编号, <br/>例如: <br/>采用列编号: <br/> dw_1.object.data <br/>dw_1.getitemstring(3,2) <br/>采用列名称表示某列: <br/> dw_1.object.article_text <br/> dw_1.getitemstring(3,"dhhm") <br/> dw_1.setitem(3,"date",1999-03-31) <br/> ... <br/>对于以上两种方法, 如果只进行一次查询, 在速度上并没有太大的区别,如过需要循环访问数据窗口上的某一列, 则速度上的差异就表现的比较明显,才用第一种方法要快, 但是程序的可读性比较差。但是, 在使用函数时(如 GETITEM() 和 setitem() ), 执行速度往往没有很大差别。 <br/>9、 计算域 <br/>数据窗口的计算域会对数据的操作性能产生影响。 如果数据窗口中包含许多复杂的计算域,将严重影响数据窗口的执行速度。 <p><font face="Courier">string da_dh[] <br/>da_dh[] = dw_1.object.dhhm.current</font></p><p><font face="Courier">这个方法头一次见到. 新奇.</font></p> 这是个好贴哦 看看 <p>顶</p> <p>好贴</p> <p>高见!学习学习!!!</p> <div class="msgheader">QUOTE:</div><div class="msgborder"><b>以下是引用<i>JohnPhan</i>在2007-10-11 9:04:08的发言:</b><br/><p><font face="Courier">string da_dh[] <br/>da_dh[] = dw_1.object.dhhm.current</font></p>
<p><font face="Courier">这个方法头一次见到. 新奇.</font></p></div>
<p>这是直接得到指定列的所有行,不用循环了</p>
页:
[1]