Proc 是Oracle提供的一種資料庫操作的API,它是基于ESql技術的,需要預編譯后才可以變成普通c代碼,非常不直觀,使用起來不太方便,閱讀也存在困難,
因為這些問題導致程式員平時開發中會出現一些Proc操作存在效率低下的情況,本文介紹一些Proc一些編譯經驗,希望能給大家提供參考,
下面以一個簡單需求進行舉例說明:
要求把DB1里面一張資料表tbl_hch_test的資料匯出到DB2的同名表,
最快的方法當然是使用oracle的資料泵工具進行壓碩訓出再匯入,但expdp/impdp對資料庫環境有特別要求,所以我們需要使用Proc編程,先從DB1取出資料,再insert到Db2里面,
簡單實作:
打開一個游標,從DB1回圈FETCH資料出來,再使用sprintf拼裝成insert陳述句,到DB2使用exec sql指令執行插入并提交資料庫,
優化:
雖然上面的做法可以完成需求,但在效率上存在不優化空間,下面依次進行介紹:
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》
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/83169.html
標籤:C++
