求教C#做两个数据库的数据交换,哪种方式最快?

BOOMKIT 2011-07-18 05:37:34
求教C#做两个数据库的数据交换,哪种方式最快?

现在是从一个数据库时一条条循环插入,慢得受不了.
...全文
218 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
sdl2005lyx 2011-07-28
  • 打赏
  • 举报
回复
直接用Sql 的脚本命令。。。。
xlg3030 2011-07-21
  • 打赏
  • 举报
回复
批量插入 。。。。。
zhangyincheng 2011-07-21
  • 打赏
  • 举报
回复
新手围观学习中
isjoe 2011-07-21
  • 打赏
  • 举报
回复
如果必须用C#,应该尽量一次性从源数据库多读取数据,然后写目标数据库的时候不能一条一条的写,会非常慢的,拼装N多条insert或Update语句,分几次写入,速度会大幅提升成千上百倍。
BOOMKIT 2011-07-21
  • 打赏
  • 举报
回复
还是用 SqlDataAdapter Update 算了
a344586704 2011-07-21
  • 打赏
  • 举报
回复
8楼的 也太给力了...

围观下
白s菜 2011-07-21
  • 打赏
  • 举报
回复
批量事务
绿色夹克衫 2011-07-19
  • 打赏
  • 举报
回复
to:ls,既然是自己写程序导表,至少可以用一下bcp(sql server的话)或表值参数(2008的话),
个人感觉还是用订阅发布比较好,另外很久以前的印象中Sql server的计划任务可以干这个,新版本的没用过这方面的功能。
hualiang_ll 2011-07-19
  • 打赏
  • 举报
回复
这个是我以前做项目参考的一篇文章,我用的是C#,我在项目里面用的就是这个办法。如果你是用Sql Server,推荐使用DTS工具。
原文的链接地址是http://blog.csdn.net/axman/article/details/2200840

对于海量数据的插入和更新,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加入要插入的行,达到一定数量提交后清空该表就行了,
实现起来并不算复杂:






DateTime begin = DateTime.Now;
string connectionString = ......;
using(SqlConnection conn = new SqlConnection(connectionString))...{
conn.Open();
SqlDataAdapter sd = new SqlDataAdapter();
sd.SelectCommand = new SqlCommand("select devid,data_time,data_value from CurrentTest", conn);
sd.InsertCommand = new SqlCommand("insert into CurrentTest (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;

DataSet dataset = new DataSet();
sd.Fill(dataset);
Random r = new Random(1000);
for (int i = 0; i < 100000; i++) ...{
object[] row = ...{"DEVID"+i,DateTime.Now.ToString("yyyy-MM-dd HH: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();

}
TimeSpan ts = 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条数据只要几个循环就行了.





DateTime begin = DateTime.Now;
string connectionString = "";
using(SqlConnection conn = new SqlConnection(connectionString))...{
conn.Open();

SqlDataAdapter sd = new SqlDataAdapter();
sd.SelectCommand = new SqlCommand("select top 200 devid,data_time,data_value from CurrentTest", conn);

DataSet dataset = new DataSet();
sd.Fill(dataset);
Random r = new Random(1000);

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 count = 0; count < 100000;)
...{

for (int i = 0; i < 200; i++,count++)
...{
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"+count;
dataset.Tables[0].Rows[i].EndEdit();
}
sd.Update(dataset.Tables[0]);
}


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

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

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

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

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

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

KAO,没有更优雅的方法了.只好将就这样用了.
PerDign 2011-07-19
  • 打赏
  • 举报
回复
拿分走人
  • 打赏
  • 举报
回复
不要处理一条记录一个事务。对于sql server来说,你不开启事务,那么它会自动地开启一个任务。应该1000条记录才使用一个事务。

另外,插入记录之前不要做任何“查询重复”之类的判断。
xiaomingtage 2011-07-19
  • 打赏
  • 举报
回复
关键是连上,连上后用“from [B的ip].B数据库名字.B1”访问吧。
试试这样行不行。
BOOMKIT 2011-07-19
  • 打赏
  • 举报
回复
两个数据库是放在异地的啊,
xiaomingtage 2011-07-18
  • 打赏
  • 举报
回复
可以不通过C#,你可以用这种方法试一下。
假设有A,B两个数据库。
1.先在A SQL上面建立到B SQL得Linking server
2.打开查询分析器(SQL Query Analyzer)连接到A数据库,
当然塞入的资料的列数要与A数据库中的表相同
假设A数据库的表为A1,B数据库表为B1
直接执行
insert A1
select column1,column2,column3....from [B的ip].B数据库名字.B1
where ...
这个查询B1表的限制条件自行添加,还有需要塞入的列的名字也要自行添加
失落的code 2011-07-18
  • 打赏
  • 举报
回复
难道不能直接换数据文件……
TobeNotTobe 2011-07-18
  • 打赏
  • 举报
回复
不经过c#最快,直接数据库同步

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧