`
yesjavame
  • 浏览: 687161 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

在C#中完成海量数据的批量插入和更新

阅读更多


对于海量数据的插入和更新,ADO.NET确实不如JDBC做到好,JDBC有统一的模型来进行批操作.使用起来
非常方便:
PreparedStatement ps = conn.prepareStatement("insert or update arg1,args2....");
然后你就可以
for(int i=0;i<1000000000000000;i++){
ps.setXXX(realArg);
.....
ps.addBatch();
if(i%500==0){//假设五百条提交一次
ps.executeBatch();
//clear Parame Batch
}
}
ps.executeBatch();

这样的操作不仅带来极度大的性能,而且非常方便.按说,ADO.NET中,要实现这样的功能,应该直接在Command接口中
或DataAdapter接口中提供Addbat和CommitBat的API,但ADO.NET的却并没有这样简单地实现,而是要求开发者通过
复杂的变通方法.
对于大量的插入操作,可以利用一个空的DataTable加入要插入的行,达到一定数量提交后清空该表就行了,
实现起来并不算复杂:

DateTimebegin=DateTime.Now;
stringconnectionString=......;
using(SqlConnectionconn=newSqlConnection(connectionString))...{
conn.Open();
SqlDataAdaptersd
=newSqlDataAdapter();
sd.SelectCommand
=newSqlCommand("selectdevid,data_time,data_valuefromCurrentTest",conn);
sd.InsertCommand
=newSqlCommand("insertintoCurrentTest(devid,data_time,data_value)"
+"values(@devid,@data_time,@data_value);",conn);
sd.InsertCommand.Parameters.Add(
"@devid",SqlDbType.Char,18,"devid");
sd.InsertCommand.Parameters.Add(
"@data_time",SqlDbType.Char,19,"data_time");
sd.InsertCommand.Parameters.Add(
"@data_value",SqlDbType.Int,8,"data_value");
sd.InsertCommand.UpdatedRowSource
=UpdateRowSource.None;
sd.UpdateBatchSize
=0;

DataSetdataset
=newDataSet();
sd.Fill(dataset);
Randomr
=newRandom(1000);
for(inti=0;i<100000;i++)...{
object[]row=...{"DEVID"+i,DateTime.Now.ToString("yyyy-MM-ddHH:mm:ss"),r.Next(1,1000)};
dataset.Tables[
0].Rows.Add(row);
if(i%300==0)...{
sd.Update(dataset.Tables[
0]);
dataset.Tables[
0].Clear();
}

}

sd.Update(dataset.Tables[
0]);
dataset.Tables[
0].Clear();
sd.Dispose();
dataset.Dispose();
conn.Close();

}

TimeSpants
=DateTime.Now-begin;
MessageBox.Show(
"ts="+ts.TotalMilliseconds);

对于这个测试我插入10万条数据用时28秒.性能还算可圈可点.但是对于批量更新,搜遍全球的例子,都是把记录Fill到DataSet中然后牧举rows
来更新,就我这个小数据量的测试而言,把10万条数据Fill到DataSet中已经不能工作,如果是百万,千万如何操作?难道一定先把要批操作的记录
先获取到DataSet中?也就是我要更新哪些记录就要选查询这些记录?

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

sd.SelectCommand = new SqlCommand("select devid,data_time,data_value from CurrentTest where 1=0", conn);
//1=0的条件保证取一个空表.
sd.UpdateCommand = new SqlCommand("update CurrentTest set data_time = @data_time,data_value = @data_value where devid = @devid", conn);
sd.UpdateCommand.Parameters.Add("@data_time", SqlDbType.Char, 19, "data_time");
sd.UpdateCommand.Parameters.Add("@data_value", SqlDbType.Int, 4, "data_value");
sd.UpdateCommand.Parameters.Add("@devid", SqlDbType.Char, 20, "devid");
sd.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;
sd.UpdateBatchSize = 0;

for(int i=0;i<300;i++){
..............................
dataset.Tables[0].Rows.Add(row);
}
sd.Update(dataset.Tables[0]);
先更新300条试试,如果成功再循环更新所有记录,但提示插入操作需要InsertCommand,因为一个空表然后Add Row操作.这时RowState是Added,如果这时Update到数据库,执行的就是插入操作而无法更新.


改成:
for(int i=0;i<300;i++){
..............................

row = {填入初始化的值};
dataset.Tables[0].Rows.Add(row);
}
dataset.AcceptChanges();
for(int i=0;i<300;i++){
..............................
dataset.Tables[0].Rows[i][x] = "xxxxxxx";
..............................
}
sd.Update(dataset.Tables[0]);
先在DataTable中插入数据,然后用AcceptChanges(),修改RowState为UnChanged,再修改表中数据希望改变UnChanged状态,即将DataTable从Current状态改为Original,然后再对DataTable的Row进行更新,就能使

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


调整思路,先从数据库中取200条(批更新的Size大小),直接得到一个Original的DataTable.
sd.SelectCommand = new SqlCommand("select top 200 devid,data_time,data_value from CurrentTest", conn);
DataSet dataset = new DataSet();
sd.Fill(dataset);
用这200个空间来放要更新的其它数据看看:

for (int i = 0; i < 100; i++)
{
dataset.Tables[0].Rows[i].BeginEdit();
dataset.Tables[0].Rows[i]["data_time"] = "2222-22-22 22:22:22";
dataset.Tables[0].Rows[i]["data_value"] = 100;
dataset.Tables[0].Rows[i]["devid"] = "DEVID"+(i+10000);//更新DEVID10000到DEVID10200的记录
dataset.Tables[0].Rows[i].EndEdit();
}
sd.Update(dataset.Tables[0]);
OK,成功,哈哈.把要更新的数据不断往这个空间填,填满就提交,这样更新100000条数据只要几个循环就行了.


DateTimebegin=DateTime.Now;
stringconnectionString="";
using(SqlConnectionconn=newSqlConnection(connectionString))...{
conn.Open();

SqlDataAdaptersd
=newSqlDataAdapter();
sd.SelectCommand
=newSqlCommand("selecttop200devid,data_time,data_valuefromCurrentTest",conn);

DataSetdataset
=newDataSet();
sd.Fill(dataset);
Randomr
=newRandom(1000);

sd.UpdateCommand
=newSqlCommand("updateCurrentTest"
+"setdata_time=@data_time,data_value=@data_valuewheredevid=@devid",conn);
sd.UpdateCommand.Parameters.Add(
"@data_time",SqlDbType.Char,19,"data_time");
sd.UpdateCommand.Parameters.Add(
"@data_value",SqlDbType.Int,4,"data_value");
sd.UpdateCommand.Parameters.Add(
"@devid",SqlDbType.Char,20,"devid");
sd.UpdateCommand.UpdatedRowSource
=UpdateRowSource.None;
sd.UpdateBatchSize
=0;
for(intcount=0;count<100000;)
...{

for(inti=0;i<200;i++,count++)
...{
dataset.Tables[
0].Rows[i].BeginEdit();
dataset.Tables[
0].Rows[i]["data_time"]="2222-22-2222:22:22";
dataset.Tables[
0].Rows[i]["data_value"]=100;
dataset.Tables[
0].Rows[i]["devid"]="DEVID"+count;
dataset.Tables[
0].Rows[i].EndEdit();
}

sd.Update(dataset.Tables[
0]);
}



dataset.Tables[
0].Clear();
sd.Dispose();
dataset.Dispose();
conn.Close();

}

TimeSpants
=DateTime.Now-begin;
MessageBox.Show(
"ts="+ts.TotalMilliseconds);

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

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

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

这个操作更新10万条用了32秒,还算勉强吧.

KAO,没有更优雅的方法了.只好将就这样用了.

分享到:
评论

相关推荐

    C#中海量数据的批量插入和更新[顶].pdf

    在C#中处理海量数据的批量插入和更新是一项常见的任务,尤其是在大数据应用或者ETL(提取、转换、加载)流程中。尽管ADO.NET在某些方面可能不如JDBC提供那么直观和便捷的批量操作API,但它仍然提供了高效的方法来...

    SqlBulkCopy批量插入海量数据

    5. **打开数据库连接**:在进行数据批量插入前,确保数据库连接已打开。 ```csharp connection.Open(); ``` 6. **执行批量插入**:最后,调用WriteToServer方法开始批量插入数据。这可以是DataTable、...

    C#海量数据瞬间插入到数据库的方法.docx

    在C#中处理海量数据插入数据库时,效率是至关重要的,因为传统的逐条插入方法可能会导致性能瓶颈。本文将详细探讨如何使用C#配合Oracle数据库的Array Binding特性,实现批量插入,以大幅提升数据插入速度。 首先,...

    C#在MySQL大量数据下的高效读取、写入详解

    总结,优化C#与MySQL在大数据场景下的交互,关键在于选择正确的数据访问方式(原生API优于ORM)、充分利用索引、优化数据处理逻辑以及高效地批量插入数据。通过这些策略,可以显著提高处理效率,降低资源消耗,使...

    c#实现几种数据库的大数据批量插入

    在之前只知道SqlServer支持数据批量插入,殊不知道Oracle、SQLite和MySQL也是支持的,不过Oracle需要使用Orace.DataAccess驱动,今天就贴出几种数据库的批量插入解决方法。 首先说一下,IProvider里有一个用于实现...

    C#Hibernate数据库海量读写快速存储

    在IT行业中,数据库管理和高效的读写操作是至关重要的任务,特别是在处理海量数据时。本话题主要探讨了如何利用C#编程语言以及Hibernate ORM框架,在SQL Server数据库上实现快速的存储和检索。以下是对这些关键知识...

    C#如何在海量数据下的高效读取写入MySQL

    在处理海量数据时,C#和MySQL的组合需要优化策略以确保高效的数据读取和写入。以下将详细探讨在不同阶段如何优化这些操作。 ### 第一步:解决读取问题 1. **避免重型ORM框架**:对于大规模数据处理,重型ORM如...

    sql批量写入数据

    在SQL Server数据库管理中,批量写入数据是一项重要的任务,特别是在处理海量数据时,效率尤为重要。批量插入可以显著提高性能,减少与数据库的交互次数,从而优化系统资源的使用。以下将详细介绍如何实现“sql批量...

    经过测试,总结出可运行成功的C#For HBase示例代码

    将C#与HBase结合,可以为.NET开发者提供处理海量数据的能力。 标题"经过测试,总结出可运行成功的C# For HBase示例代码"表明,这里包含的是一系列已经经过验证的C#代码片段,它们能够成功地与HBase进行交互,执行...

    海量数据分页源码(gridview 分页)

    在现代软件开发过程中,特别是Web应用中,处理海量数据时如何优化用户体验、提高数据加载速度是非常关键的一环。分页技术就是其中一种重要的优化手段。本文将基于提供的代码示例,详细介绍如何在.NET环境中使用...

    基于数据库的海量GDF导航电子地图数据处理方法.pdf

    在处理这类数据时,面临的主要问题包括海量数据的存储、检索效率、数据格式的灵活性以及数据处理的性能等。GDF文件在定义上具有一定的灵活性,不同的数据供应商可能对同一要素有不同的字段定义。因此,处理GDF数据时...

    在C#中使用二叉树实时计算海量用户积分排名的实现详解

    在C#中,使用二叉树实现实时计算海量用户积分排名是一种高效的方法,尤其适用于需要频繁更新和查询排名的场景。传统的解决方案通常涉及定时批量处理积分计算,将结果存储在中间表中,或者仅显示顶级用户的排行榜。...

    ACCESS导入SQL数据库的系列方法

    3. **使用Linked Server**:在SQL Server中创建一个指向Access数据库的链接服务器,可以方便地进行数据交互,如查询、插入、更新和删除操作。配置过程包括:在“服务器对象”-&gt;“链接服务器”中新建链接服务器,指定...

    asp.net面试题及参考答案

    8. **海量数据插入问题**:当大量插入数据导致数据库报错时,可能的原因包括:磁盘空间不足、内存溢出、事务过大等。解决方案可以是分批插入、优化SQL语句、增加索引、调整数据库参数或使用批量导入工具。 9. **...

    深入云计算 MongoDB管理与开发实战详解pdf.part2

    3.1.2 批量插入 3.2 删除文档 3.3 修改文档 3.3.1 整个文档的替换 3.3.2 使用修改器 3.3.3 upsert和save更新 3.3.4 修改多个文档 3.3.5 修改文档并返回修改后的文档 3.4 数据库响应 3.4.1...

    MongoDB学习手册

    - **名称来源**:MongoDB的名称来源于英文单词“humongous”,意指其能够处理海量数据的能力。 - **定位**:MongoDB是一款开源的、面向文档存储的NoSQL数据库系统。 - **平台兼容性**:支持多种操作系统平台,包括...

    net 笔试题汇总

    8. **海量数据插入优化**:大数据量插入可能导致数据库报错,可能的原因有内存不足、表锁定、索引冲突等。解决方法包括分批插入、禁用索引、调整数据库参数、使用批量插入语句、优化事务大小等。 9. **数据去重算法...

Global site tag (gtag.js) - Google Analytics