.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...