在日常的業務系統應用中大家經常會使用到大量數據的的提交(包括查詢更新或刪除)假如目標數據庫的數據量較大一次需要處理的操作較多就會出現系統執行效率低下等問題文本中筆者以Oraclei數據庫為例通過對ADONet中的數據庫支持的應用實踐說明幾種常見的優化處理方法並對比其中的優劣
為了更詳細說明情況筆者以某業務數據填報功能為例假設有個用戶每周需要填報某統計數量填報明細的數據量約為條有專門的填報頁面實現一次提交這樣一周的數據增量約為萬一年為多萬要保證系統有效運行年以上需要考慮數據存儲(增刪改)效率問題(數據庫本身的優化配置包括表空間索引等查詢效率已經考慮不在此討論范疇)這類業務的特點是數據操作量較大但執行的指令復雜度較低包含簡單的新增修改刪除類
傳統處理方法存在的問題
對每一個要處理的操作直接對目標表執行對應的SQL操作(或存儲過程)可使用ADONet的參數化SQL或通過DataSet與DataAdapter來間接處理這樣每個用戶批量提交數據時需要執行大約次SQL操作雖然數據庫進行了優化單次執行SQL的效率並不低但由於一次執行的指令較多隨著目標數據容量的增加效率會逐步降低最終不可忍受
優化方法臨時表處理模式
對於大規模的目標數據庫表進行多次修改刪除或更新操作效率必定較慢要降低對目標表的操作次數可以采用臨時表的解決辦法具體方法為建立一個與目標表結構類似的臨時表(由於B/S模式的特點臨時表是基於事務的而不是基於連接的)並增加操作模式標記字段在執行操作前將本次要操作的數據就是某個用戶每周的數據(約條左右第一次處理時應該沒有數據)一次查詢轉入臨時表再對臨時表執行修改更新刪除(作刪除標記)操作處理完畢後分別將臨時表的數據分三類提交到目標表流程如下圖所示
刪除
Delete From TARGET_TABLE Where KEY In(Select KEY
From TEMP_TABLE Where STATE=Delete
新增
Insert Into TARGET_TABLE …
Select … From TEMP_TABLE Where STATE=Insert
修改
Update TARGET_TABLE Set …
Where KEY=TEMP_TABLEKET AND TEMP_TABLESTATE=Update
實驗證明在萬數據量的條件下此方法能比傳統的方法快倍左右且執行效率受目標數據庫容量的影響較小
優化方法使用SQL批處理
SQL批處理一般有種模式一種是將要執行的SQL語句連接形成批處理指令一次提交到服務器執行一種是對執行的SQL指令傳遞多組參數批執行這兩種方法都需要數據庫及ADONet的支持
SystemDataOracleClient 的ADONet 版本支持第一種方式的的批處理如通過DataAdapter對DataSet的批量數據提交時系統會根據數據集合中的新增修改刪除標識構造批處理指令形成SQL指令段提交服務器執行這種方式是將多個SQL指令形成一組SQL指令的方法實現多個指令的批執行能一定程度提高功能的執行效率原理如下所示
Begin
Insert Into TAREGT_TABLE(ABC) Values()
Insert Into TAREGT_TABLE(ABC) Values()
Insert Into TAREGT_TABLE(ABC) Values()
……
Insert Into TAREGT_TABLE(ABC) Values(nn+n+)
end
此方法形成的批處理SQL指令及參數會隨著數據量的增加而成倍增加數據更新量與執行效率受到限制而微軟的Oracle ADONet實現並沒有將批處理方法直接對外公開只能通過DataSet的數據批量更新間接使用
另一種處理方法是使用Oracle的ADONet實現OracleDataAccessClient實現的ADONet支持第二種模式的批處理指令其利用Oracle數據庫自帶的批處理功能通過設定OracleCommand的ArrayBindCount來實現對參數數組的傳遞當ArrayBindCount設置為大於時傳遞給一個OracleCommand的參數不再是參數值而是參數數組這樣一條Command指令就可以執行多個處理如插入條數據使用這種方法利用了數據庫本身對批量數據操作的優化機制極大提高了數據操作效率通過對目標數據庫容量為萬的目標表測試發現此方法執行比傳統方法的執行效率提高倍以上在測試過程中發現萬的目標數據量的情況下一次插入萬條數據只需要秒左右且操作效率受目標數據量的影響較小
總結
通過以上的分析我們可以得出以下結論采用臨時表的方法及批處理的手段都能較好解決大規模數據量模式下的批量數據提交的問題其中Oracle的ADONet的實現效率最高處理最簡單微軟ADONet的實現沒有完全利用數據庫本身的功能功能及效率受到局限而臨時表的處理方法編程比較復雜適合於在使用微軟的ADONet的情況下使用更進一步Oracle存儲過程支持參數數組的傳遞也可以采用通過傳遞參數數組的存儲過程來實現前提也是必須采用Oracle的ADONet實現因為微軟的ADONet實現不支持參數數組傳遞而Oracle數據庫也支持Bulk Insert功能如果有批量的數據需要插入可以考慮使用此方法此處不詳細討論
這種方法將對目標數據庫表的次SQL操作轉化為對臨時表的數據庫操作由於臨時表數據量少效率較高且周期穩定而最後的數據更新只涉及到臨時表到目標表的有限的次SQL操作不涉及到ADONet與數據庫的數據交互效率相對較高
From:http://tw.wingwit.com/Article/program/Oracle/201311/18337.html