詳解C 中利用ODP實現瞬間匯入百萬級資料

2021-09-30 06:38:31 字數 4202 閱讀 6412

.net程式中可以通過odp呼叫特性,對oracle資料庫進行操作,今天來講一下資料批量插入的功能,所用技術不高不深,相信很多朋友都接觸過,小弟班門弄斧了,呵呵。這篇文章是上篇文章的續集,因為上一次試驗的徵集結果沒有突破4秒的方法,所以這次繼續挑戰與挖掘新方法,雖然是oracle,但仍具有一定收藏意義。

極限挑戰—c#100萬條資料匯入sql server資料庫僅用4秒 (附原始碼)

這個試驗是針對sql server資料庫的,宿主環境也是.net,有興趣的朋友可以將這兩個試驗對比一下,為日後工作批量導數提供支援。

另外,一些朋友對上次試驗環境有些異議,認為應該對資料庫和伺服器做優化或設定,以體現試驗最終的時間結果。這個固然會影響試驗的時間結果,但考慮到在試驗環境中,對資料庫優化的標準與優化程度不便統一與定量,試驗結果也不易說明其影響源,所以這次試驗依然以標準資料庫建庫後的配置為主,試驗所在伺服器硬體環境與上次試驗保持一致。實驗目的在於挖掘、對比宿主程式中的資料批量操作方法。

有新方法提公升效能時間指標的朋友,歡迎互相切磋,互相提高,嘴上功夫就免了。。。

好了正文開始。

普通肉墊式

什麼叫批量插入呢,就是一次性插入一批資料,我們可以把這批資料理解為乙個大的陣列,而這些全部只通過乙個sql來實現,而在傳統方式下,需要呼叫很多次的sql才可以完成,這就是著名的「陣列繫結」的功能。我們先來看一下傳統方式下,插入多行記錄的操作方式:

//設定乙個資料庫的連線串,  

stringconnectstr = "user id=scott;password=tiger;data source="

;   

oracleconnection conn =neworacleconnection(connectstr);  

oraclecommand command =neworaclecommand(); 

command.connection = conn; conn.open();   

stopwatch sw =newstopwatch();   

sw.start(); //通過迴圈寫入大量的資料,這種方法顯然是肉墊 

for(inti = 0; i 

sw.stop();  

system.diagnostics.debug.writeline("普通插入:"

+ recc.tostring()

+ sw.elapsedmilliseconds.tostring());   

我們先準備好程式,但是先不做時間的測定,因為在後面我們會用多次迴圈的方式來計算所占用的時間。

使用odp特性

//設定乙個資料庫的連線串  

stringconnectstr = "user id=scott;password=tiger;data source="

;   

oracleconnection conn =neworacleconnection(connectstr);   

oraclecommand command =neworaclecommand();   

command.connection = conn; //到此為止,還都是我們熟悉的**,下面就要開始嘍 

//這個引數需要指定每次批插入的記錄數 

command.arraybindcount = recc;   

//在這個命令列中,用到了引數,引數我們很熟悉,但是這個引數在傳值的時候 

//用到的是陣列,而不是單個的值,這就是它獨特的地方 

command.commandtext = "insert into dept values(:deptno, :deptname, :loc)"

;   

conn.open();   

//下面定義幾個陣列,分別表示三個字段,陣列的長度由引數直接給出 

intdeptno =new

int[recc];   

stringdname =new

string[recc];   

stringloc =new

string[recc];   

// 為了傳遞引數,不可避免的要使用引數,下面會連續定義三個 

// 從名稱可以直接看出每個引數的含義,不在每個解釋了 

oracleparameter deptnoparam =neworacleparameter("deptno"

,   

oracledbtype.int32);   

deptnoparam.direction = parameterdirection.input;   

deptnoparam.value = deptno; command.parameters.add(deptnoparam);   

oracleparameter deptnameparam =neworacleparameter("deptname"

,   

oracledbtype.varchar2);  

deptnameparam.direction = parameterdirection.input;   

deptnameparam.value = dname;   

command.parameters.add(deptnameparam);  

oracleparameter deptlocparam =neworacleparameter("loc"

, oracledbtype.varchar2); 

deptlocparam.direction = parameterdirection.input;  

deptlocparam.value = loc;   

command.parameters.add(deptlocparam);   

stopwatch sw =newstopwatch();   

sw.start();   

//在下面的迴圈中,先把陣列定義好,而不是像上面那樣直接生成sql 

for(inti = 0; i 

//這個呼叫將把引數陣列傳進sql,同時寫入資料庫 

command.executenonquery(); 

sw.stop(); 

system.diagnostics.debug.writeline("批量插入:"

+ recc.tostring()   

+sw.elapsedmilliseconds.tostring());  

以上**略顯冗長,但是加上注釋後基本也就表達清楚了。

好了,到目前為止,兩種方式的插入操作程式已經完成,就剩下對比了。我在主函式處寫了乙個小函式,迴圈多次對兩個方法進行呼叫,並且同時記錄下時間,對比函式如下:

for(inti = 1; i <= 50; i++)  

當資料量達到100萬級別時,所用時間依然令人滿意,最快一次達到890毫秒,一般為1秒左右。

經過試驗,得出一組資料,可以看出兩種方式在效率方面驚人的差距(占用時間的單位為毫秒),部分資料如下:

記錄數標準

批處理

因為篇幅原因,不再貼上全部的資料,但是我們可以看一下由此資料生成的散點圖:

其中有些資料有些跳躍,可能和資料庫本身有關係,但是大部分資料已經能說明問題了。看了這些資料後,是不是有些心動了?

源程式放了一段時間直接拷貝貼過來了,可能需要除錯一下才能跑通,不過不是本質性問題,對了如果要測試別忘記安裝oracle訪問元件。

C 利用最新版的WPS實現匯入匯出

注 微軟的excel操作相信大家也知道,不方便,安裝包太大,而且 的資料量也只有6000多 是6000多還是60000多我就忘記了 在匯出匯入大量資料的就沒辦法,而wsp 則實現了百萬資料的容量,而且安裝包也小,操作更方便。下面利用最wps2015實現了乙個簡單的匯入到出,參考文章,也可也參考一下w...

C 利用最新版的WPS實現匯入匯出

微軟的excel操作相信大家也知道,不方便,安裝包太大,而且 的資料量也只有6000多 是6000多還是60000多我就忘記了 在匯出匯入大量資料的就沒辦法,而wsp 則實現了百萬資料的容量,而且安裝包也小,操作更方便。下面利用最wps2015實現了乙個簡單的匯入到出,參考文章,也可也參考一下wsp...

術 c 中利用反射實現深拷貝

c 中深拷貝不常用,但是需要的時候如果沒有,實在是麻煩的很。今天聊天,中梁大神說他實現了乙個,趕緊學習學習。廢話少說,直接上 using system using system.collections using system.collections.generic using system.ref...