c#

位置:IT落伍者 >> c# >> 浏览文章

.net对海量数据的插入与更新


发布日期:2023年06月15日
 
.net对海量数据的插入与更新
对于海量数据的插入和更新ADONET确实不如JDBC做到好JDBC有统一的模型来进行批操作使用起来

非常方便

PreparedStatement ps = connprepareStatement(insert or update argargs

然后你就可以

for(int i=;i<;i++){

pssetXXX(realArg)

……

psaddBatch()

if(i%==){ //假设五百条提交一次

psexecuteBatch()

//clear Parame Batch

}

}

psexecuteBatch()

这样的操作不仅带来极度大的性能而且非常方便按说ADONET中要实现这样的功能应该直接在Command接口中

或DataAdapter接口中提供Addbat和CommitBat的API但ADONET的却并没有这样简单地实现而是要求开发者通过

复杂的变通方法

对于大量的插入操作可以利用一个空的DataTable加入要插入的行达到一定数量提交后清空该表就行了

实现起来并不算复杂

DateTime begin = DateTimeNow;

string connectionString = ……

using(SqlConnection conn = new SqlConnection(connectionString))…{

connOpen()

SqlDataAdapter sd = new SqlDataAdapter()

sdSelectCommand = new SqlCommand(select deviddata_timedata_value from CurrentTest conn)

sdInsertCommand = new SqlCommand(insert into CurrentTest (deviddata_timedata_value)

+ values (@devid@data_time@data_value) conn)

sdInsertCommandParametersAdd(@devid SqlDbTypeChar devid

sdInsertCommandParametersAdd(@data_time SqlDbTypeChar data_time

sdInsertCommandParametersAdd(@data_value SqlDbTypeInt data_value

sdInsertCommandUpdatedRowSource = UpdateRowSourceNone;

sdUpdateBatchSize = ;

DataSet dataset = new DataSet()

sdFill(dataset)

Random r = new Random(

for (int i = ; i < ; i++) …{

object[] row = …{DEVID+iDateTimeNowToString(yyyyMMdd HH:mm:ssrNext() };

datasetTables[]RowsAdd(row)

if (i % == ) …{

sdUpdate(datasetTables[])

datasetTables[]Clear()

}

}

sdUpdate(datasetTables[])

datasetTables[]Clear()

sdDispose()

datasetDispose()

connClose()

}

TimeSpan ts = DateTimeNow begin;

MessageBoxShow(ts = + tsTotalMilliseconds)

对于这个测试我插入万条数据用时性能还算可圈可点但是对于批量更新搜遍全球的例子都是把记录Fill到DataSet中然后牧举rows

来更新就我这个小数据量的测试而言万条数据Fill到DataSet中已经不能工作如果是百万千万如何操作?难道一定先把要批操作的记录

先获取到DataSet中?也就是我要更新哪些记录就要选查询这些记录?

于是我仍然利用一个空的DataTable来加入要更新的记录

sdSelectCommand = new SqlCommand(select deviddata_timedata_value from CurrentTest where = conn)

//=的条件保证取一个空表

sdUpdateCommand = new SqlCommand(update CurrentTest set data_time = @data_timedata_value = @data_value where devid = @devid conn)

sdUpdateCommandParametersAdd(@data_time SqlDbTypeChar data_time

sdUpdateCommandParametersAdd(@data_value SqlDbTypeInt data_value

sdUpdateCommandParametersAdd(@devid SqlDbTypeChar devid

sdUpdateCommandUpdatedRowSource = UpdateRowSourceNone;

sdUpdateBatchSize = ;

for(int i=;i<;i++){

……

datasetTables[]RowsAdd(row)

}

sdUpdate(datasetTables[])

先更新条试试如果成功再循环更新所有记录但提示插入操作需要InsertCommand因为一个空表然后Add Row操作这时RowState是Added如果这时Update到数据库执行的就是插入操作而无法更新

改成

for(int i=;i<;i++){

……

row = {填入初始化的值};

datasetTables[]RowsAdd(row)

}

datasetAcceptChanges()

for(int i=;i<;i++){

……

datasetTables[]Rows[i][x] = xxxxxxx;

……

}

sdUpdate(datasetTables[])

先在DataTable中插入数据然后用AcceptChanges()修改RowState为UnChanged再修改表中数据希望改变 UnChanged状态即将DataTable从Current状态改为Original然后再对DataTable的Row进行更新就能使

Update成功但这样做确实不方便

调整思路先从数据库中取条(批更新的Size大小)直接得到一个Original的DataTable

sdSelectCommand = new SqlCommand(select top deviddata_timedata_value from CurrentTest conn)

DataSet dataset = new DataSet()

sdFill(dataset)

用这个空间来放要更新的其它数据看看

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

{

datasetTables[]Rows[i]BeginEdit()

datasetTables[]Rows[i][data_time] = ::;

datasetTables[]Rows[i][data_value] = ;

datasetTables[]Rows[i][devid] = DEVID+(i+//更新DEVID到DEVID的记录

datasetTables[]Rows[i]EndEdit()

}

sdUpdate(datasetTables[])

OK成功哈哈把要更新的数据不断往这个空间填填满就提交这样更新条数据只要几个循环就行了

DateTime begin = DateTimeNow;

string connectionString = ;

using(SqlConnection conn = new SqlConnection(connectionString))…{

connOpen()

SqlDataAdapter sd = new SqlDataAdapter()

sdSelectCommand = new SqlCommand(select top deviddata_timedata_value from CurrentTest conn)

DataSet dataset = new DataSet()

sdFill(dataset)

Random r = new Random(

sdUpdateCommand = new SqlCommand(update CurrentTest

+ set data_time = @data_timedata_value = @data_value where devid = @devid conn)

sdUpdateCommandParametersAdd(@data_time SqlDbTypeChar data_time

sdUpdateCommandParametersAdd(@data_value SqlDbTypeInt data_value

sdUpdateCommandParametersAdd(@devid SqlDbTypeChar devid

sdUpdateCommandUpdatedRowSource = UpdateRowSourceNone;

sdUpdateBatchSize = ;

for (int count = ; count < ;)

…{

for (int i = ; i < ; i++count++)

…{

datasetTables[]Rows[i]BeginEdit()

datasetTables[]Rows[i][data_time] = ::;

datasetTables[]Rows[i][data_value] = ;

datasetTables[]Rows[i][devid] = DEVID+count;

datasetTables[]Rows[i]EndEdit()

}

sdUpdate(datasetTables[])

}

datasetTables[]Clear()

sdDispose()

datasetDispose()

connClose()

}

TimeSpan ts = DateTimeNow begin;

MessageBoxShow(ts = + tsTotalMilliseconds)

注意上面的更新操作是指在一个十万百万千万条记录中我要不断更新其中的记录这些要更新的记录并不是从头

到尾这样的顺序只是不断地根据条件更新任何记录我不可能把成百上千万记录先Fill到ds中然后在ds中Select到

这条记录然后更新所以每次更新操作填入一次DataTable中提交就实现了JDBC的addBat和executeBat操作

这个操作更新万条用了还算勉强吧

               

上一篇:C#3.0之对象与集合初始化

下一篇:C# 2010命名和可选参数的新特性