最佳化你的PowerBuilder程式

來源:互聯網
上載者:User
 一段程式,完成了所需要的功能固然重要,但是提高執行效率,提高代碼的可重複利用性,提高程式的可讀性也是很重要的。剛剛讀了一個前輩的文章,感覺受益菲淺,拿將出來與大家共用

最佳化你的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_2 的下拉資料視窗共用 DW_1
        datawindowchild child2
        dw_3.getchild('dhhm',child2)
        child2.settransobject(sqlca)
        dw_1.sharedata(child1)
    使用這種方法, 避免了各個資料視窗間物理的拷貝資料, 因此減少了空間上的開銷,提高了應用程式的綜合效能.
4. 資料視窗間資料的拷貝
    如果需要在資料視窗間共用資料, 應當盡量使用 SHAREDATA() 函數, 但是, SHAREDATA() 函數並不是物理地在資料視窗間拷貝資料, 如工在顯示資料的同時, 還要對資料進行操作, 則需要進行資料的拷貝.
例如, 要求將 DW_1 中選定的行拷貝到 DW_2 中:
    在視窗的 OPEN 事件中編程:
        dw_1.settransobject(sqlca)
        dw_2.settransobject(sqlca)
        dw_1.retrieve()
    在資料視窗 DW_1 的 ROWFOCUSCHANGED 事件中編寫下列程式:  
        long lr  
        lr = dw_1.selectrow(0,false)
        lr = dw_1.getrow()
        lr = dw_1.selectrow(lr,true)
要完成從 DW_1 到 DW_2 的拷貝工作, 有兩種方法:
第一種:  
在按鈕 "拷貝" 的 CLICKED 事件中編程
long lr  
lr = dw_1.getselectedrow(0)
dw_1.rowscopy(lr,lr,primary!,dw_2,100,primary!)
執行程式, 利用 POWERBUILDER PROFILER 得出所需時間為 1.7034(百分之一秒)
第二種:  
在按鈕 "拷貝" 的 CLICKED 事件中編程
dw_2.object.data = da_1.object.data.selected
執行程式, 利用 POWERBUILDER PROFILER 得出所需時間為 0.8062(百分之一秒)
5. 資料視窗屬性的訪問和修改
A. 資料視窗屬性的訪問
    在程式中訪問資料視窗的屬性有下列幾種方法:
    A1. 採用點運算式訪問
    A2. 應用多個獨立的 DESCRIBE() 函數訪問
    A3. 只使用一個 DESCRIBE() 函數, 採用複合參數訪問多個屬性
上面三中方法, 通常第一種方法最慢, 第三種方法最快.  
例如:  
    在視窗的 OPEN 事件中
    DW_1.SETTRANSOBJECT(SQLCA)
    DW_1.RETRIEVE()
第一種方法:  
在檢索按鈕的 CLICKED 事件中編程.
    string dx, dy, dh, dw
    dx = dw_1.object.da_dh.x
    dy = dw_1.object.da_dh.y
    dx = dw_1.object.da_dh.height
    dy = dw_1.object.da_dh.width
    st_1.text =dx+","+dy+","+dh+","+dw
第二種方法:
    string dx, dy, dh, dw
    dx=dw_1.describe("da_dh.x")
    dx=dw_1.describe("da_dh.y")
    dx=dw_1.describe("da_dh.height")
    dx=dw_1.describe("da_dh.width")
    st_1.text =dx+","+dy+","+dh+","+dw
第三種方法:
    string dx, dy, dh, dw
    st_1.text=dw_1.describe("da_dh.x" +&
                            "da_dh.y" +&
                            "da_dh.height" +&
                            "da_dh.width")
實驗證明, 第三種方法的速度是最快的. 但是程式的可讀性最差.
B. 資料視窗屬性的修改
在程式中修改資料視窗的屬性有下列幾種方法:
    A1. 採用點運算式修改
    A2. 應用多個獨立的 MODIFY() 函數訪問
    A3. 只使用一個 MODIFY() 函數, 採用複合參數訪問多個屬性
上面三中方法, 通常第一種方法最慢, 第三種方法最快.  
例如:  
    在視窗的 OPEN 事件中
    DW_1.SETTRANSOBJECT(SQLCA)
    DW_1.RETRIEVE()
第一種方法:  
在檢索按鈕的 CLICKED 事件中編程.
    DW_1.SETREDRAW(FALSE)
    dw_1.object.da_dh.x = 18
    dw_1.object.da_dh.y = 16
    dw_1.object.da_dh.height = 100
    dw_1.object.da_dh.width = 200
    DW_1.setredraw(true)
    st_1.text =dx+","+dy+","+dh+","+dw
第二種方法:
    DW_1.SETREDRAW(FALSE)
    dw_1.modify("da_dh.x = 18")
    dw_1.modify("da_dh.y = 16")
    dw_1.modify("da_dh.height = 100")
    dw_1.modify("da_dh.width = 200")
    dw_1.setredraw(true)
第三種方法:
    dw_1.modify("da_dh.x=18" +&
                "da_dh.y=16" +&
                "da_dh.height=100" +&
                "da_dh.width=200")
實驗證明, 第三種方法的速度是最快的. 但是程式的可讀性最差.注意, 在方法一和方法二中, 都使用的 setredraw() 函數以減少螢幕的重繪, 否則, 執行速度將嚴重下降.
6. 資料視窗中資料的訪問  
在程式中, 經常會需要動態修改資料視窗中的資料. 對此, PB 提供了多種方法, 各種方法在效能上會有一些差異.
A. 資料視窗中資料的訪問
    目的: 將資料視窗中的電話號碼存放在一個數組中.請比較下面兩中方法.
    方法一:
    string da_dh[]
    long ll,i  
    ll = dw_1.rowcount()
    for i = ll to 1 stet -1
    da_dh[i] = 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[i] = 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、 計算域
資料視窗的計算域會對資料的操作效能產生影響。 如果資料視窗中包含許多複雜的計算域,將嚴重影響資料視窗的執行速度。  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.