首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > PB >

[转帖]关于PB编程的一点经验,该如何解决

2012-02-24 
[转帖]关于PB编程的一点经验原文:http://bbs.51cto.com/viewthread.php?tid409234PowerBuilder是快速有效

[转帖]关于PB编程的一点经验
原文:http://bbs.51cto.com/viewthread.php?tid=409234 
 PowerBuilder是快速有效的开发工具,在程序实现过程灵活 
多样,下面介绍一下在开发高校产品过程中积累的一些经验。 
一、处理 SQL 语句 

1、缓冲 SQL 语句 
  在应用程序中,有时需要反复调用同一组 SQL语句, 
在这种情况下,可以通过在应用中为这些 SQL 建立缓冲区来 
提高执行性能。 
  在缺省情况下,SQL 语句的缓冲区是关闭的,你可以 
通过如下语句打开它: 
  SQLCACHE = n 
  n 表示装入缓冲区的 SQL 语句数量(缺省为0)。 
  例如: 
  dw_1.SetTransObject(sqlca) 
  SQLCA.dbParm = "SQLCache = 0" 
  dw_1.retrieve() 

  如果将上例的 "SQLCache = 0" 改为 "SQLCache = 25", 
此句的执行效率将提高五分之一左右。但应注意缓冲区的大小, 
否则也将影响程序执行的性能。 
  注:此方法对用 ODBC 和 ORACLE 连接的数据库非常有效。 

2、捆绑变量 
  请看下例: 
  SQLCA.DBPARM = "DISABLEBIND=1" 

  INSERT INTO DA_DH VALUES("1","河南0") 
  INSERT INTO DA_DH VALUES("2","河南1") 
  INSERT INTO DA_DH VALUES("3","河南2") 
  INSERT INTO DA_DH VALUES("4","河南3") 
  INSERT INTO DA_DH VALUES("5","河南4") 
  INSERT INTO DA_DH VALUES("6","河南5")  

  这里未使用捆绑变量,在插入是 PB 将重新处理每个带有 
  新值的SQL语句。如果将上例改为: 
  SQLCA.DBPARM = "DISABLEBIND=0" 

  INSERT INTO DA_DH VALUES("1","河南0") 
  INSERT INTO DA_DH VALUES("2","河南1") 
  INSERT INTO DA_DH VALUES("3","河南2") 
  INSERT INTO DA_DH VALUES("4","河南3") 
  INSERT INTO DA_DH VALUES("5","河南4") 
  INSERT INTO DA_DH VALUES("6","河南5")  

  则系统将把 INSERT 语句按如下格式进行处理: 
  INSERT INTO DA_DH VALUES(?,?) 
  其中 "?" 称为占位符。系统性能将有所增强。 
3、用数据窗口代替 SQL 语句 

通常,为了获得某些数据,采用数据窗口和 SQL 语句都是可行的, 
但是PB 对数据窗口和 SQL 语句采用不同的处理机制,因此, 
具有不同的效率。 

例:为里检索电话档案中的用户名,可以利用 SQL 语句,  

将所有的数据检索到一个多行编辑中,也可以检索到一个数据窗口中。 
如果使用第一中方法: 
首先定义一个游标: 

  DECLARE CUR CURSOR FOR  
  SELECT "DA_DH"."HM" 
  FROM "DA_DH"; 
然后可以: 

  STRING stxt[],st 
  int li 

  open cur 
  do li = li + 1 
  fetch cur 
  into :stxt[li] ; 
  st=st+stxt[li] + "~r~n" 
  loop while stxt[li]"" 
  close cur; 
  mle_1.txt = st 

也可以使用第二种方法:  
  dw_1.settransobject(sqlca) 
  dw_1.retrieve() 
  利用 POWERBUILDER PROFILER 工具进行检查,对比两种 
方法所需时间如下 
方法 所需时间 (百分之一秒) 
SQL 语句    100.9857 
数据窗口 49.0133  

  由于数据窗口或 DATASTORE 使用了标准的内嵌的代码, 
而不是有开发人员进行全部编码,同时编译执行的速度比解释 
执行的速度快的多,因此在开发过程中应尽量使用数据窗口和 
DATASTORE.. 即使是必须用 SQL 语句的时候,也应该尽量 
将它们定义为存储过程(特别是在多用户的环境中),以提高 
应用程序的性能. 

二、数据窗口的编程和执行 

数据窗口是PB最值得被称道的, 其具有如下特点: 
1. 多种显示方式. 
2. 多种编辑方式. 
3. 使用方法简单. 
4. 具有多种报表形式. 
5. 可实现屏幕滚动. 
6. 可实现数据的有效性校验. 
7. 执行性能显著提高. 
8. 编程工作变少. 
9. 可以在数据窗口内部实现数据库的更新. 

下面, 我将介绍一些用于提高数据窗口性能的技术. 




1. 减少连接数据库的次数 

连库操作是非常影响执行速度的操作. 因此在程序中,一旦与数据库连接后 
就应当尽量保持与数据库的连接, 减少连接数据库的次数.  
PowerBuilder 提供里两个函数来建立数据窗口与事务对象的连接: 
  SetTrans()  
  SetTransObject() 
在程序中应当尽量使用 SETTRANSOBJECT(), 因为SETTRANS() 函数在每次 
调用 RETRIEVE(), UPDATE() 等函数之后, 都要执行数据库的连接和断开操作. 

2. 下拉数据窗口与表的连接 

  对于数据库服务器来说, 表的连接操作是一项非常大的开销, 而 POWERBUILDER 提供的下拉数据窗口在某些情况下可以代替表的连接操作. 

例如, 为了在数据窗口上显示用户的电话号码和姓名: 
如果用表的连接的方法, 数据窗口对应的 SQL 语句应是这样的: 
  SELECT "DA_DH"."DHHM", 
  "DA_HTH"."DWM" 
  FROM "DA_HTH", 
  "DA_DH" 
  WHERE ("DA_HTH"."DHHM"="DA_DH"."DHHM") 
同样的程序可用下拉数据窗口来完成, 这里不再具体介绍. 
但是, 应当注意, 以上两种方法究竟哪一种数据更快, 与表的结构, 表的 
数量, 连接的方法等均有关系, 应当具体分析. 
3. 共享数据 
在一个应用程序中, 某些数据需要频繁的使用, 如果在每次使用时都从数据库 
中进行检索, 则需占用大量的服务器资源和网络资源. 为了减少开销, 可以在客户 
端对这些数据只进行一次检索, 然后允许其它任务共享这些数据.  

例如, 如果有两个数据窗口, 都需要从第三方表中检索出用户的电话号码, 且此 
列用下拉数据窗口给出. 如果每次都对电话号码进行检索, 则性能较低. 因此, 可 
以单独建立一个关于电话号码的数据窗口. 在每次打开窗口时, 首先将电话号码检 
索到此数据窗口中, 然后另外两个数据窗口中关于电话号码的下拉数据窗口可以共享 
此数据窗口中的数据. 

在窗口的 OPEN 事件中编写如下程序: 

  dw_1.settransobject(sqlca) 
  dw_2.settransobject(sqlca)  
  dw_3.settransobject(sqlca)  
  // 检索 dw_1  
  dw_1.retrieve() 

  // 使 DW_2 的下拉数据窗口共享 DW_1 
  datawindowchild child1 
  dw_2.getchild('dhhm',child1) 
  child1.settransobject(sqlca) 
  dw_1.sharedata(child1) 

  // 使 DW_3 的下拉数据窗口共享 DW_1 
  datawindowchild child2 
  dw_3.getchild('dhhm',child2) 
  child2.settransobject(sqlca) 
  dw_1.sharedata(child2) 
使用这种方法, 避免了各个数据窗口间物理的拷贝数据, 因此减少了空间上的开销,提高了应用程序的综合性能. 


4. 数据窗口间数据的拷贝 

如果需要在数据窗口间 
 = dw_1.getitemstring(i,"dhhm") 
  next 
  方法二:  
  string da_dh[] 
  da_dh[] = dw_1.object.dhhm.current 

测试发现, 第二种方法比第一种方法快将近一倍. 数据量越大 
这种差异越明显. 

B. 数据窗口中数据的修改 

  目的: 修改数据窗口中的电话号码列的值. 
  请比较下面两中方法. 
  方法一: 
  dw_1.setitem(i,"dhhm",l_name) 
  方法二:  
  dw_1.object.name
 = l_name 

测试发现, 第二种方法比第一种方法快将近一倍. 数据量越大 
这种差异越明显. 

7. 数据窗口事件对性能的影响 

对于数据窗口控制中经常发生的事件, 应当尽量减少其中的程序代码. 
特别是如下事件: 
  A. itemchanged 
  b. editchanged 
  c. itemfocuschanged 
  d. pbm_dwnkey 
  e. rowfocuschanged 
  f. retrieverow 
在这些事件中的任何处理程序, 都会降低应用程序的处理速度. 所以 
应当尽量减少这些事件中的处理程序, 必要时, 可以考虑只将重要的代码 
放在这些事件中, 而将剩余的代码放在一个传递的事件中. 

例如,如果需要用到数据窗口的 ROWFOCUSCHANGED 事件,可以为数据 
窗口定义一用户事件 "UE_RE", 而在数据窗口的 ROWFOCUSCHANGED 事件 
中写如下代码: 

  PARENT.postevent("ue_re") 
  在 UE_RE 事件中再编写相应的程序代码,如: 
  string code  
  dw_1.selectrow(0,false) 
  dw_1.selectrow(rownum,true) 
  code = getitemstring(dw_1,rownum,"dhhm") 

  dw_2.retrieve(code) 

另外, 为了获得当前行号,应尽量使用数据窗口的 CURRENTROW 变量, 
而少用 GETROW() 函数。 



8、 数据窗口的列名称与列编号 

对数据窗口的某列进行访问, 可以采用该列的名称, 也可以使用该列的编号, 
例如: 
采用列编号: 

  dw_1.object.data[ll_row,2] 
  dw_1.getitemstring(3,2) 

采用列名称表示某列: 

  dw_1.object.article_text[ll_row] 
  dw_1.getitemstring(3,"dhhm") 
  dw_1.setitem(3,"date",1999-03-31) ... 
对于以上两种方法, 如果只进行一次查询, 在速度上并没有太大的区别, 
如过需要循环访问数据窗口上的某一列, 则速度上的差异就表现的比较明显, 
才用第一种方法要快, 但是程序的可读性比较差。 
但是, 在使用函数时(如 GETITEM() 和 setitem() ), 执行速度往往 
没有很大差别。 

9、 计算域 

数据窗口的计算域会对数据的操作性能产生影响。 如果数据窗口中包含许多 
复杂的计算域,将严重影响数据窗口的执行速度。 



[解决办法]
呵呵,好贴
[解决办法]
好帖
[解决办法]
好贴,通常这些都没考虑,现在大多数服务器的运行效率还是比较高滴
[解决办法]
MK

热点排行