一段程序完成所需要的功能固然重要但是提高執行效率提高代碼的可重復利用性提高程序的可讀性也是很重要的剛剛讀了一個前輩的帖子感覺受益匪淺拿出來與大家共享
優化你的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() ) 執行速度往往沒有很大差別
計算域
數據窗口的計算域會對數據的操作性能產生影響 如果數據窗口中包含許多復雜的計算域將嚴重影響數據窗口的執行速度
From:http://tw.wingwit.com/Article/program/SQL/201311/16334.html