大批量数据更新,分享给大家。

wnttmk 2014-05-09 02:16:52
今天要做一个大批量的数据分析,在表数据中要加入一些字段。并且通过程序分析得出有效值后存入数据库中。以方便接下来的操作。
好吧,数据量也不是很大。只有55W条。通过数据导出将他从服务器上导出单表数据后。存入本地的数据库中。所以,所有的字段都设置为Varchar类型,没有主键。
老老实实的写方法,首先通过ADO.NET中的SQLCommand来执行吧。也就是说一条数据执行一条。每次从数据库中读取100条。分析完后执行SQL语句。
new SqlCommand("Update order_db Set Sex = @Sex, Age = @Age where Ord_No = @Ord_No", conn).ExecuteNonQuery();

平均速度为1秒<10条。纠结!~~55W条数据啊!~~

好吧,另寻方法吧!这次使用ADO.NET中的SqlDataAdapter进行批量数据更新吧。同样,每次从数据库中取100条。批量进行数据更新
 SqlDataAdapter sda = new SqlDataAdapter();
sda.SelectCommand = command;
sda.UpdateCommand = new SqlCommand("Update order_db Set Sex = @Sex, Age = @Age where Ord_No = @Ord_No", conn);
sda.UpdateCommand.Parameters.Add("@Sex", SqlDbType.VarChar, 50, "sex");
sda.UpdateCommand.Parameters.Add("@Age", SqlDbType.VarChar, 50, "Age");
sda.UpdateCommand.Parameters.Add("@Ord_No", SqlDbType.VarChar, 50, "Ord_No");


对ds的所有dataRow更新后执行更新
 sda.Update(ds);
ds.AcceptChanges();


速度小有提升,因为与执行SQL语句的方法类似所以不太明显。这要是要处理这么多数据也要一大段时间。恼火。
这时,突然想起曾经在做数据采集时用到的一个对象——SqlBulkCopy。这玩意很特殊,只能插入,但是速度那真不是吹出来的。1W条数据进行写入时可能就1秒不到。
头脑风暴来了,因为是数据分析,所以数据的安全性可以不用考虑。我设想删除的动作会非常快。然后再写入进去不就可以了。
步骤就是取出到一个dataset中,然后对dataset中的值进行更改。然后删除掉数据库中的数据,再用SqlBulkCopy拷贝进去就可以了。
 var lq = from t in ds.Tables[0].AsEnumerable()
select new
{
ordNo = t.Field<string>("Ord_No")
};
List<string> ordList = new List<string>();
foreach (var q in lq)
{
ordList.Add(q.ordNo);
}
string k = string.Join("','", ordList.ToArray());
Console.WriteLine(DateTime.Now.ToString() + "删除原始订单");
new SqlCommand()
{
CommandText = "Delete From order_db Where Ord_No In('" + k + "')",
Connection = conn,
CommandType = CommandType.Text
}.ExecuteNonQuery();
Console.WriteLine(DateTime.Now.ToString() + "添加新订单");
SqlBulkCopy bulkCopy = new SqlBulkCopy(conn);
bulkCopy.DestinationTableName = ("order_db");
bulkCopy.BatchSize = ds.Tables[0].Rows.Count;
foreach (DataColumn dc in ds.Tables[0].Columns)
{
bulkCopy.ColumnMappings.Add(dc.ColumnName, dc.ColumnName);
}
bulkCopy.WriteToServer(ds.Tables[0]);
bulkCopy.Close();


实践证明,速度真的不是一般的快。55W条数据不到几分钟就全部处理完了,而且最大的速度浪费居然是在数据读取和分析上。因为没有主键,所以读取数据时速度大约要5秒左右。

呵呵,发出来大家一起探讨一下。不知道对于大批量数据是否还有更好的处理办法。
...全文
642 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
wnttmk 2014-05-12
  • 打赏
  • 举报
回复
引用 6 楼 uinatlex 的回复:
你确定是你UPDATE的时候慢 而不是处理数据的时候?
我很确定,因为UPDATE的时候要使用一个字段作为标识,而我这个表里面没有设置主键、索引之类的。所以速度相当的慢。
uinatlex 2014-05-09
  • 打赏
  • 举报
回复
你确定是你UPDATE的时候慢 而不是处理数据的时候?
wnttmk 2014-05-09
  • 打赏
  • 举报
回复
引用 3 楼 nitaiyoucala 的回复:
可以通过线程来操作,50一组。。。
线程试过了,线程多了跑起来费力。而且,SQL的锁死机制是个短板。多个线程同时select和upload时会出现死锁的情况.带上unlock和rowlock也会有锁死的情况。
  • 打赏
  • 举报
回复
SqlBulkCopy公司不需用,因为瞬间的IO压力太大。。。。会导致其它访问出现问题 然后DBA推荐用的是MSSQL2005还是MSSQL2008新出来的一种批量增加方式。。。具体叫啥的忘了。。。。。忘了。。。。。。。
nitaiyoucala 2014-05-09
  • 打赏
  • 举报
回复
可以通过线程来操作,50一组。。。
wnttmk 2014-05-09
  • 打赏
  • 举报
回复
引用 1 楼 diaodiaop 的回复:
首先 这么大的批量应该只有一次吧.. 而且"分析得出有效值"应该可以通过update from where 来解决.. 而且具体业务先不说 你先删除 然后在插入 我个人觉得办法不是很好.. 因为他们不是一个事物 万一writetoserver中断 你就完了..
分析的话要取的值比较多,这里没一一列出。如地区,性别,年龄,手机更换频率等。而且还要判断是否有异常值。一条Update Case when解决不了,在存储过程中写比较麻烦。 我也知道先删后加的办法不是安全的做法。希望和大家一起探讨更佳的方法。
by_封爱 2014-05-09
  • 打赏
  • 举报
回复
首先 这么大的批量应该只有一次吧.. 而且"分析得出有效值"应该可以通过update from where 来解决.. 而且具体业务先不说 你先删除 然后在插入 我个人觉得办法不是很好.. 因为他们不是一个事物 万一writetoserver中断 你就完了..

62,073

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

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