国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

C#中使用ODP瞬間導(dǎo)入百萬級數(shù)據(jù)的方法

2023-05-11 12:02:25
字體:
供稿:網(wǎng)友

.Net程序中可以通過ODP調(diào)用特性,對Oracle數(shù)據(jù)庫進(jìn)行操作,今天來講一下數(shù)據(jù)批量插入的功能,所用技術(shù)不高不深,相信很多朋友都接觸過。

(1)普通肉墊式

什么叫批量插入呢,就是一次性插入一批數(shù)據(jù),我們可以把這批數(shù)據(jù)理解為一個大的數(shù)組,而這些全部只通過一個SQL來實現(xiàn),而在傳統(tǒng)方式下,需要調(diào)用很多次的SQL才可以完成,這就是著名的“數(shù)組綁定”的功能。我們先來看一下傳統(tǒng)方式下,插入多行記錄的操作方式:

//設(shè)置一個數(shù)據(jù)庫的連接串,

string connectStr = "User Id=scott;Password=tiger;Data Source=";

OracleConnection conn
= new
OracleConnection(connectStr);

OracleCommand command
= new
OracleCommand();

command.Connection
=
conn;

conn.Open();

Stopwatch sw
= new
Stopwatch();

sw.Start();


//通過循環(huán)寫入大量的數(shù)據(jù),這種方法顯然是肉墊


for (int i = 0; i < recc; i++)

{


string sql = "insert into dept values(" +
i.ToString()

+ "," + i.ToString() + "," + i.ToString() + ")"
;

command.CommandText
=
sql;

command.ExecuteNonQuery();

}

sw.Stop();

System.Diagnostics.Debug.WriteLine(
"普通插入:" +
recc.ToString()

+ "所占時間:" + sw.ElapsedMilliseconds.ToString());

我們先準(zhǔn)備好程序,但是先不做時間的測定,因為在后面我們會用多次循環(huán)的方式來計算所占用的時間。

(2)使用ODP特性

看上面的程序,大家都很熟悉,因為它沒有用到任何ODP的特性,而緊接著我們就要來介紹一個神奇的程序了,我們看一下代碼,為了更直觀,我把所有的注釋及說明直接寫在代碼里:

//設(shè)置一個數(shù)據(jù)庫的連接串

string connectStr = "User Id=scott;Password=tiger;Data Source=";

OracleConnection conn
= new
OracleConnection(connectStr);

OracleCommand command
= new
OracleCommand();

command.Connection
=
conn;

//
到此為止,還都是我們熟悉的代碼,下面就要開始嘍

//這個參數(shù)需要指定每次批插入的記錄數(shù)


command.ArrayBindCount = recc;

//
在這個命令行中,用到了參數(shù),參數(shù)我們很熟悉,但是這個參數(shù)在傳值的時候

//用到的是數(shù)組,而不是單個的值,這就是它獨特的地方


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

conn.Open();


//下面定義幾個數(shù)組,分別表示三個字段,數(shù)組的長度由參數(shù)直接給出


int[] deptNo = new int[recc];

string[] dname = new string
[recc];

string[] loc = new string
[recc];

//
為了傳遞參數(shù),不可避免的要使用參數(shù),下面會連續(xù)定義三個

// 從名稱可以直接看出每個參數(shù)的含義,不在每個解釋了


OracleParameter deptNoParam = new OracleParameter("deptno",

OracleDbType.Int32);

deptNoParam.Direction
=
ParameterDirection.Input;

deptNoParam.Value
=
deptNo;

command.Parameters.Add(deptNoParam);

OracleParameter deptNameParam
= new OracleParameter("deptname"
,

OracleDbType.Varchar2);

deptNameParam.Direction
=
ParameterDirection.Input;

deptNameParam.Value
=
dname;

command.Parameters.Add(deptNameParam);

OracleParameter deptLocParam
= new OracleParameter("loc"
,

OracleDbType.Varchar2);

deptLocParam.Direction
=
ParameterDirection.Input;

deptLocParam.Value
=
loc;

command.Parameters.Add(deptLocParam);

Stopwatch sw
= new
Stopwatch();

sw.Start();


//在下面的循環(huán)中,先把數(shù)組定義好,而不是像上面那樣直接生成SQL


for (int i = 0; i < recc; i++)

{

deptNo[i]
=
i;

dname[i]
=
i.ToString();

loc[i]
=
i.ToString();

}


//這個調(diào)用將把參數(shù)數(shù)組傳進(jìn)SQL,同時寫入數(shù)據(jù)庫


command.ExecuteNonQuery();

sw.Stop();

System.Diagnostics.Debug.WriteLine(
"批量插入:" + recc.ToString()

+ "所占時間:" +sw.ElapsedMilliseconds.ToString());

 以上代碼略顯冗長,但是加上注釋后基本也就表達(dá)清楚了。

當(dāng)數(shù)據(jù)量達(dá)到100萬級別時,所用時間依然令人滿意,最快一次達(dá)到890毫秒,一般為1秒左右。

好了,到目前為止,兩種方式的插入操作程序已經(jīng)完成,就剩下對比了。我在主函數(shù)處寫了一個小函數(shù),循環(huán)多次對兩個方法進(jìn)行調(diào)用,并且同時記錄下時間,對比函數(shù)如下:

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

{

Truncate();

OrdinaryInsert(i
* 1000
);

Truncate();

BatchInsert(i
* 1000
);

}

 經(jīng)過試驗,得出一組數(shù)據(jù),可以看出兩種方式在效率方面驚人的差距(占用時間的單位為毫秒),部分?jǐn)?shù)據(jù)如下:

記錄數(shù)

標(biāo)準(zhǔn)

批處理

1000

1545

29

2000

3514

20

3000

3749

113

4000

5737

40

5000

6820

52

6000

9469

72

7000

10226

69

8000

15280

123

9000

11475

83

10000

14536

121

11000

15705

130

12000

16548

145

13000

18765

125

14000

20393

116

15000

22181

159

因為篇幅原因,不再粘貼全部的數(shù)據(jù),但是我們可以看一下由此數(shù)據(jù)生成的散點圖:

ODP導(dǎo)入百萬條數(shù)據(jù)

其中有些數(shù)據(jù)有些跳躍,可能和數(shù)據(jù)庫本身有關(guān)系,但是大部分?jǐn)?shù)據(jù)已經(jīng)能說明問題了??戳诉@些數(shù)據(jù)后,是不是有些心動了?

源程序放了一段時間直接拷貝貼過來了,可能需要調(diào)試一下才能跑通,不過不是本質(zhì)性問題,對了如果要測試別忘記安裝Oracle訪問組件。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 鄢陵县| 南涧| 福鼎市| 堆龙德庆县| 招远市| 巴南区| 巴中市| 定州市| 普洱| 璧山县| 体育| 通化市| 筠连县| 城固县| 句容市| 宁津县| 苗栗市| 西宁市| 广州市| 济阳县| 广汉市| 平远县| 鸡东县| 甘谷县| 鲁山县| 黔东| 华安县| 贵州省| 西青区| 武陟县| 新邵县| 武邑县| 临沭县| 固镇县| 蓝山县| 万安县| 治多县| 抚州市| 许昌县| 孟津县| 昭苏县|