Proc 是Oracle提供的一種數據庫操做的AP。它是基於ESql技術的,須要預編譯後才能夠變成普通c代碼,很是不直觀,使用起來不太方便,閱讀也存在困難。程序員
由於這些問題致使程序員平時開發中會出現一些Proc操做存在效率低下的狀況,本文介紹一些Proc一些編譯經驗,但願能給你們提供參考。sql
下面以一個簡單需求進行舉例說明:數據庫
要求把DB1裏面一張數據表tbl_hch_test的數據導出到DB2的同名表。編程
最快的方法固然是使用oracle的數據泵工具進行壓縮導出再導入,但expdp/impdp對數據庫環境有特別要求,因此咱們須要使用Proc編程,先從DB1取出數據,再insert到Db2裏面。數組
簡單實現:服務器
打開一個遊標,從DB1循環FETCH數據出來,再使用sprintf拼裝成insert語句,到DB2使用exec sql指令執行插入並提交數據庫。網絡
優化:oracle
雖然上面的作法能夠完成需求,但在效率上存在不優化空間。下面依次進行介紹:app
1 使用綁定變量代替sprintf拼裝sql函數
實踐證實sprintf函數在對效率要求比較高的場景下容易成爲性能瓶頸,使用綁定變量能夠避免sprintf調用。
而且,因爲數據庫裏面執行的sql是相同的,不須要每次從新分析sql生成執行計劃,也能大大減輕數據庫負擔,提升執行效率。
2 對insert語句進行預編譯,一次編譯屢次執行,避免使用隱性遊標,每次都要從新編譯。
同上,預編譯是比較消耗cpu的操做。若是sql相同,能夠複用遊標,減小性能開支。
3 使用批量操做,每次取數和插入數據都使用數組進行綁定。
批量操做能夠減小客戶端與服務器之間交互次數,加快操做數據。
4 適當加大事務提交間隔(insert多行記錄commit一次)
Oracle提交數據庫事務時須要將日誌從內存刷回磁盤並等待磁盤操做完成才返回,提升事務提交間隔能夠減小等待消耗。
優化先後效率測試對比:
相同的操做,從23s下降到1.3s
其它提升效率措施:
以上是在編程上的一些優化,結合oracle一些特性,速度還能再提高,簡單介紹幾個優化技巧:
1 先刪除目標表索引,insert完數據後再重建
2 關閉表的日誌, 減小redo日誌,alter table tbl_hch_test nologing。裝載完數據再改回來。
3 使用append HINT,在高水位上面直接插入數據,加快插入速度。
4 使用並行(parallel)查詢,或者使用分區查詢(select * from tab parttion(par_name))加快查詢速度。
5 若是可能,儘可能在數據庫服務器上執行程序,減小網絡傳輸開銷
關鍵代碼參考:
另外,附上幾個平時使用Proc容易出現誤區。
1 使用char數組保存數據庫varchar2類型字段的值
Proc的char數組對應的數據庫類型是char,varchar結構體對應的類型纔是varchar2。使用char數組保存數據庫varchar2類型字段的值,會致使取出的數據像char類型同樣,在末尾自動添加空格。
解決方法可使用EXEC SQL VAR/ EXEC SQL TYPE同等化變量或者數據類型。或者在預編譯時指定CHAR_MAP=string一勞永役
2 須要注意proc的一些命令是預編譯命令,只在預編譯期間生效,與C語言的宏十分類似。例如如下命令:。
EXEC SQL CONTEXT USE
ESEC SQL Whenever Sqlerror Do
下面舉一個常見的錯誤進行說明:
要徹底搞明白proc的原理,建議多分析.pc文件與porc預編譯後生成的.c文件代碼區別。
3 proc指針變量
Proc能夠正確識別指針與普通變量,使用指針作爲綁定變量與使用普通變量的方法同樣,在變量前面加上冒號便可。
官方文檔是這樣說的:
有一些程序員不清楚怎麼在proc使用指針,會使用memcpy把數據複製多一遍,增長無謂消耗。
4 proc與C語言宏
Proc能識別C語言的一些簡單的宏,但若是有複雜的宏(如不定參數宏),proc在預編譯時會報錯。
此時能夠考慮使用gcc –E先對.pc文件進行預處理,以後再使用proc進行預編譯。
若是對於proc編程還有什麼其它疑惑的地方,歡迎你們與我討論,或者查閱官方幫助文檔。《Oracle Proc官方文檔.pdf》