.net大批量数据的数据操作的性能消耗问题
公司的导入奖池的程序一直有问题,小数据量没有任何问题,但如果有2000条以上的数据导入时,就会很明显的感觉到很慢很慢。由于一直忙,没有找到好的解决方法。
今天终于算是找到好的解决方法了。
经过测试,本地数据导入内网SQL Server中5w多条数据,耗时为1秒中左右。飞一般的感觉。
解决方案的核心是:SqlBulkCopy
这是.net2.0新增的一个类,可以解决批量数据导入问题。使您可以用其他源的数据有效批量加载 SQL Server 表。
官方的解释:
Microsoft SQL Server 提供一个称为 bcp 的流行的命令提示符实用工具,用于将数据从一个表移动到另一个表(表既可以在同一个服务器上,也可以在不同服务器上)。SqlBulkCopy 类允许编写提供类似功能的托管代码解决方案。还有其他将数据加载到 SQL Server 表的方法(例如 INSERT 语句),但相比之下 SqlBulkCopy 提供明显的性能优势。
使用 SqlBulkCopy 类只能向 SQL Server 表写入数据。但是,数据源不限于 SQL Server;可以使用任何数据源,只要数据可加载到 DataTable 实例或可使用 IDataReader 实例读取数据。
下面是我写的关于批量导入的核心代码。copy下来,作为备份学习。
[code lang="csharp"]
/// <summary>
/// 大批量数据
/// </summary>
/// <param name="dt"></param>
private void ToSqlServerExtension(DataTable dt)
{
string strCon = System.Configuration.ConfigurationManager.ConnectionStrings["GameTradingCon"].ToString();
//创建连接
SqlConnection sqlCon = new SqlConnection(strCon);
sqlCon.Open();
DateTime beginTime = DateTime.Now;
using (SqlBulkCopy sqlBC=new SqlBulkCopy(strCon))//用于执行大批量数据
{
//一次批量插入的数据量
sqlBC.BatchSize = 1000;
//超时之前操作完成所允许的秒数,如果超时则事务不会提交 ,数据将回滚,所有已复制的行都会从目标表中移除
sqlBC.BulkCopyTimeout = 60;
//設定 NotifyAfter 属性,以便在每插入10000 条数据时,呼叫相应事件。
sqlBC.NotifyAfter = 1000;
//设置要批量写入的表
sqlBC.DestinationTableName = "T_NPCgoActivityPrize";
//自定义的datatable和数据库的字段进行对应
sqlBC.ColumnMappings.Add("couponsId", "couponsId");
sqlBC.ColumnMappings.Add("couponsGroup", "couponsGroup");
sqlBC.ColumnMappings.Add("faceValue", "faceValue");
sqlBC.ColumnMappings.Add("prizeChannel", "prizeChannel");
sqlBC.ColumnMappings.Add("prizeName", "prizeName");
sqlBC.ColumnMappings.Add("prizeTypeDis", "prizeTypeDis");
sqlBC.ColumnMappings.Add("prizeSourceDis", "prizeSourceDis");
sqlBC.ColumnMappings.Add("prizeStarValidity", "prizeStarValidity");
sqlBC.ColumnMappings.Add("prizeEndValidity", "prizeEndValidity");
sqlBC.ColumnMappings.Add("useCondition", "useCondition");
sqlBC.ColumnMappings.Add("activityCreateChannel", "activityCreateChannel");
//批量写入数据
sqlBC.WriteToServer(dt);
}
sqlCon.Dispose();
DateTime endTime = DateTime.Now;
//插入成功提示
Tools.Alert("导入SqlServer成功!请查看!执行sql开始时间:"+beginTime+",结束时间:"+endTime, this.Page);
}
private DataTable GetRealData(DataSet dsExcel)
{
DataTable dtResult = new DataTable();
dtResult.Columns.Add("couponsId");
dtResult.Columns.Add("couponsGroup");
dtResult.Columns.Add("faceValue");
dtResult.Columns.Add("prizeChannel");
dtResult.Columns.Add("prizeName");
dtResult.Columns.Add("prizeTypeDis");
dtResult.Columns.Add("prizeSourceDis");
dtResult.Columns.Add("prizeStarValidity");
dtResult.Columns.Add("prizeEndValidity");
dtResult.Columns.Add("useCondition");
dtResult.Columns.Add("activityCreateChannel");
try
{
for (int i = 0; i < dsExcel.Tables[0].Rows.Count; i++)
{
if (!string.IsNullOrEmpty(dsExcel.Tables[0].Rows[i].ItemArray[0].ToString()))
{
DataRow dr = dtResult.NewRow();
dr["couponsId"] =dsExcel.Tables[0].Rows[i].ItemArray[0].ToString();
dr["couponsGroup"] = txtPCH.Value.Trim();
dr["faceValue"] = "0";
dr["prizeChannel"] = ddlPrizes.SelectedValue;
dr["prizeName"] = ddlPrizes.SelectedItem.Text;
dr["prizeTypeDis"] = txtAwardType.Text;
dr["prizeSourceDis"] = txtAwardFrom.Text;
dr["prizeStarValidity"] = dbStart.Value;
dr["prizeEndValidity"] = dbEnd.Value;
dr["useCondition"] = txtUseCondtion.Value.Trim();
dr["activityCreateChannel"] = ddlActity.SelectedItem.Text;
dtResult.Rows.Add(dr);
}
}
}
catch (Exception ex)
{
//失败提示
//Tools.Alert("导入SqlServer过程中发生错误!\n错误提示:" + ex.Message, this.Page);
GameTradingByPublic.ExceptionLog.SetExceptionLog(ex);
}
return dtResult;
}
[/code]
写个博客不容易,请转载的时候备注下原文出处,谢谢
作者:keepnode
博客地址:http://www.cnblogs.com/woaic
每件事到最后都是好事,如果不是好事,说明还没有到最后
=========================
作者:keepnode
博客地址:http://www.cnblogs.com/woaic
每件事到最后都是好事,如果不是好事,说明还没有到最后
=========================