一段程序完成所需要的功能固然重要但是提高执行效率提高代码的可重复利用性提高程序的可读性也是很重要的刚刚读了一个前辈的帖子感觉受益匪浅拿出来与大家共享
优化你的PowerBuilder程序
一处理 SQL 语句
缓沖 SQL 语句
在应用程序中有时需要反复调用同一组SQL语句在这种情况下可以通过在应用中为这些 SQL建立缓沖区来提高执行性能在缺省情况下SQL语句的缓沖区是关闭的你可以通过如下语句打开它
SQLCACHE = n
n 表示装入缓沖区的 SQL 语句数量(缺省为)
例如
dw_SetTransObject(sqlca)
SQLCAdbParm = SQLCache =
dw_retrieve()
如果将上例的 SQLCache = 改为 SQLCache = 此句的执行效率将提高五分之一左右但应注意缓沖区的大小否则也将影响程序执行的性能
注此方法对用 ODBC 和 ORACLE 连接的数据库非常有效
捆绑变量
请看下例
SQLCADBPARM = DISABLEBIND=
INSERT INTO DA_DH VALUES(河南)
INSERT INTO DA_DH VALUES(河南)
INSERT INTO DA_DH VALUES(河南)
INSERT INTO DA_DH VALUES(河南)
INSERT INTO DA_DH VALUES(河南)
INSERT INTO DA_DH VALUES(河南)
这里未使用捆绑变量再插入时 PB 将重新处理每个带有新值的SQL语句
如果将上例改为
SQLCADBPARM = DISABLEBIND=
INSERT INTO DA_DH VALUES(河南)
INSERT INTO DA_DH VALUES(河南)
INSERT INTO DA_DH VALUES(河南)
INSERT INTO DA_DH VALUES(河南)
INSERT INTO DA_DH VALUES(河南)
INSERT INTO DA_DH VALUES(河南)
则系统将把 INSERT 语句按如下格式进行处理
INSERT INTO DA_DH VALUES(??)
其中 ? 称为占位符系统性能将有所增强
用数据窗口代替 SQL 语句
通常为了获得某些数据采用数据窗口和 SQL 语句都是可行的但是PB 对数据窗口和 SQL 语句采用不同的处理机制因此具有不同的效率
例为里检索电话档案中的用户名可以利用 SQL 语句将所有的数据检索到一个多行编辑中也可以检索到一个数据窗口中
如果使用第一种方法
首先定义一个游标
DECLARE CUR CURSOR FOR
SELECT DA_DHHM
FROM DA_DH;
然后可以
STRING stxt[]st
int li
open cur
do li = li +
fetch cur
into :stxt[li] ;
st=st+stxt[li] + ~r~n
loop while stxt[li]<>
close cur;
mle_txt = st
也可以使用第二种方法
dw_settransobject(sqlca)
dw_retrieve()
利用 POWERBUILDER PROFILER 工具进行检查对比两种方法所需时间如下
方法 所需时间 (百分之一秒)
SQL 语句
数据窗口
由于数据窗口或DATASTORE使用了标准的内嵌代码而不是由开发人员进行全部编码同时编译执行的速度比解释执行的速度快的多因此在开发过程中应尽量使用数据窗口和DATASTORE即使是必须用SQL语句的时候也应该尽量将它们定义为存储过程(特别是在多用户的环境中)以提高应用程序的性能
二数据窗口的编程和执行
数据窗口是PB最值得被称道的 其具有如下特点:
多种显示方式
多种编辑方式
使用方法简单
具有多种报表形式
可实现屏幕滚动
可实现数据的有效性校验
执行性能显着提高
编程工作变少
可以在数据窗口内部实现数据哭的更新
下面 我将介绍一些用于提高数据窗口性能的技术
减少连接数据库的次数
连库操作是非常影响执行速度的操作 因此在程序中一旦与数据库连接后就应当尽量保持与数据库的连接 减少连接数据库的次数PowerBuilder 提供里两个函数来建立数据窗口与事务对象的连接:
SetTrans()
SetTransObject()
在程序中应当尽量使用 SETTRANSOBJECT() 因为SETTRANS() 函数在每次调用 RETRIEVE() UPDATE() 等函数之后 都要执行数据库的连接和断开操作
下拉数据窗口与表的连接
对于数据库服务器来说 表的连接操作是一项非常大的开销 而 POWERBUILDER 提供的下拉数据窗口在某些情况下可以代替表的连接操作例如 为了在数据窗口上显示用户的电话号码和姓名:如果用表的连接的方法 数据窗口对应的 SQL 语句应是这样的:
SELECT DA_DHDHHMDA_HTHDWM
FROM DA_HTH DA_DH
WHERE (DA_HTHDHHM=DA_DHDHHM)
同样的程序可用下拉数据窗口来完成 这里不再具体介绍但是 应当注意 以上两种方法究竟哪一种数据更快 与表的结构 表的数量 连接的方法等均有关系 应当具体分析
共享数据
在一个应用程序中 某些数据需要频繁的使用 如果在每次使用时都从数据库中进行检索 则需占用大量的服务器资源和网络资源 为了减少开销 可以在客户端对这些数据只进行一次检索 然后允许其它任务共享这些数据
例如 如果有两个数据窗口 都需要从第三方表中检索出用户的电话号码 且此列用下拉数据窗口给出 如果每次都对电话号码进行检索 则性能较低 因此 可以单独建立一个关于电话号码的数据窗口 在每次打开窗口时 首先将电话号码检索到此数据窗口中 然后另外两个数据窗口中关于电话号码的下拉数据窗口可以共享此数据窗口中的数据
在窗口的 OPEN 事件中编写如下程序:
dw_settransobject(sqlca)
dw_settransobject(sqlca)
dw_settransobject(sqlca)
// 检索 dw_
dw_retrieve()
// 使 DW_ 的下拉数据窗口共享 DW_
datawindowchild child
dw_getchild(dhhmchild)
childsettransobject(sqlca)
dw_sharedata(child)
// 使 DW_ 的下拉数据窗口共享 DW_
datawindowchild child
dw_getchild(dhhmchild)
childsettransobject(sqlca)
dw_sharedata(child)
使用这种方法 避免了各个数据窗口间物理的拷贝数据 因此减少了空间上的开销提高了应用程序的综合性能
数据窗口间数据的拷贝
如果需要在数据窗口间共享数据 应当尽量使用 SHAREDATA() 函数 但是 SHAREDATA() 函数并不是物理地在数据窗口间拷贝数据 如果在显示数据的同时 还要对数据进行操作 则需要进行数据的拷贝
例如 要求将 DW_ 中选定的行拷贝到 DW_ 中:
在窗口的 OPEN 事件中编程:
dw_settransobject(sqlca)
dw_settransobject(sqlca)
dw_retrieve()
在数据窗口 DW_ 的 ROWFOCUSCHANGED 事件中编写下列程序:
long lr
lr = dw_selectrow(false)
lr = dw_getrow()
lr = dw_selectrow(lrtrue)
要完成从 DW_ 到 DW_ 的拷贝工作 有两种方法:
第一种:
在按钮 拷贝 的 CLICKED 事件中编程
long lr
lr = dw_getselectedrow()
dw_rowscopy(lrlrprimary!dw_primary!)
执行程序 利用 POWERBUILDER PROFILER 得出所需时间为 (百分之一秒)
第二种:
在按钮 拷贝 的 CLICKED 事件中编程
dw_objectdata = da_objectdataselected
执行程序 利用 POWERBUILDER PROFILER 得出所需时间为 (百分之一秒)
数据窗口属性的访问和修改
A 数据窗口属性的访问
在程序中访问数据窗口的属性有下列几种方法:
A 采用点表达式访问
A 应用多个独立的 DESCRIBE() 函数访问
A 只使用一个 DESCRIBE() 函数 采用复合参数访问多个属性
上面三中方法 通常第一种方法最慢 第三种方法最快
例如:
在窗口的 OPEN 事件中
DW_SETTRANSOBJECT(SQLCA)
DW_RETRIEVE()
第一种方法:
在检索按钮的 CLICKED 事件中编程
string dx dy dh dw
dx = dw_objectda_dhx
dy = dw_objectda_dhy
dx = dw_objectda_dhheight
dy = dw_objectda_dhwidth
st_text =dx++dy++dh++dw
第二种方法:
string dx dy dh dw
dx=dw_describe(da_dhx)
dx=dw_describe(da_dhy)
dx=dw_describe(da_dhheight)
dx=dw_describe(da_dhwidth)
st_text =dx++dy++dh++dw
第三种方法:
string dx dy dh dw
st_text=dw_describe(da_dhx +&
da_dhy +&
da_dhheight +&
da_dhwidth)
实验证明 第三种方法的速度是最快的 但是程序的可读性最差
B 数据窗口属性的修改
在程序中修改数据窗口的属性有下列几种方法:
A 采用点表达式修改
A 应用多个独立的 MODIFY() 函数访问
A 只使用一个 MODIFY() 函数 采用复合参数访问多个属性
上面三种方法 通常第一种方法最慢 第三种方法最快
例如:
在窗口的 OPEN 事件中
DW_SETTRANSOBJECT(SQLCA)
DW_RETRIEVE()
第一种方法:
在检索按钮的 CLICKED 事件中编程
DW_SETREDRAW(FALSE)
dw_objectda_dhx =
dw_objectda_dhy =
dw_objectda_dhheight =
dw_objectda_dhwidth =
DW_setredraw(true)
st_text =dx++dy++dh++dw
第二种方法:
DW_SETREDRAW(FALSE)
dw_modify(da_dhx = )
dw_modify(da_dhy = )
dw_modify(da_dhheight = )
dw_modify(da_dhwidth = )
dw_setredraw(true)
第三种方法:
dw_modify(da_dhx= +&
da_dhy= +&
da_dhheight= +&
da_dhwidth=)
实验证明 第三种方法的速度是最快的 但是程序的可读性最差注意 在方法一和方法二中 都使用的 setredraw() 函数以减少屏幕的重绘 否则 执行速度将严重下降
数据窗口中数据的访问
在程序中 经常会需要动态的修改数据窗口中的数据 对此 PB 提供了多种方法 各种方法在性能上会有一些差异
A 数据窗口中数据的访问
目的: 将数据窗口中的电话号码存放在一个数组中请比较下面两中方法
方法一:
string da_dh[]
long lli
ll = dw_rowcount()
for i = ll to stet
da_dh[i] = dw_getitemstring(idhhm)
next
方法二:
string da_dh[]
da_dh[] = dw_objectdhhmcurrent
测试发现 第二种方法比第一种方法快将近一倍 数据量越大这种差异越明显
B 数据窗口中数据的修改
目的: 修改数据窗口中的电话号码列的值
请比较下面两中方法
方法一:
dw_setitem(idhhml_name)
方法二:
dw_objectname[i] = l_name
测试发现 第二种方法比第一种方法快将近一倍 数据量越大这种差异越明显
数据窗口事件对性能的影响
对于数据窗口控制中经常发生的事件 应当尽量减少其中的程序代码 特别是如下事件:
a itemchanged
b editchanged
c itemfocuschanged
d pbm_dwnkey
e rowfocuschanged
f retrieverow
在这些事件中的任何处理程序 都会降低应用程序的处理速度 所以应当尽量减少这些事件中的处理程序 必要时 可以考虑只将重要的代码放在这些事件中 而将剩余的代码放在一个传递的事件中
例如如果需要用到数据窗口的 ROWFOCUSCHANGED 事件可以为数据窗口定义一用户事件 UE_RE而在数据窗口的 ROWFOCUSCHANGED 事件中写如下代码
PARENTpostevent(ue_re)
在 UE_RE 事件中再编写相应的程序代码如
string code
dw_selectrow(false)
dw_selectrow(rownumtrue)
code = getitemstring(dw_rownumdhhm)
dw_retrieve(code)
另外 为了获得当前行号应尽量使用数据窗口的 CURRENTROW 变量而少用 GETROW() 函数
数据窗口的列名称与列编号
对数据窗口的某列进行访问 可以采用该列的名称 也可以使用该列的编号
例如
采用列编号
dw_objectdata[ll_row]
dw_getitemstring()
采用列名称表示某列
dw_objectarticle_text[ll_row]
dw_getitemstring(dhhm)
dw_setitem(date)
对于以上两种方法如果只进行一次查询在速度上并没有太大的区别如果需要循环访问数据窗口上的某一列则速度上的差异就表现的比较明显采用第一种方法要快 但是程序的可读性比较差但是在使用函数时(如 GETITEM() 和 setitem() ) 执行速度往往没有很大差别
计算域
数据窗口的计算域会对数据的操作性能产生影响 如果数据窗口中包含许多复杂的计算域将严重影响数据窗口的执行速度