SqlBulkCopy批量插入数据
利用SqlBulkCopy快速大批量导入数据
protected
void
Button1_Click(
object
sender, EventArgs e)
{
DateTime beginTime = DateTime.Now;
Response.Write(
"开始时间:"
+ beginTime.ToString(
"yyyy年MM月dd日:HH:mm:ss:fff"
));
//构造一个Datatable存储将要批量导入的数据
DataTable dt =
new
DataTable();
dt.Columns.Add(
"id"
,
typeof
(
string
));
dt.Columns.Add(
"name"
,
typeof
(
string
));
// 见识下SqlBulkCopy强悍之处,来个十万条数数据试验
int
i;
for
(i = 0; i < 100000; i++)
{
DataRow dr = dt.NewRow();
dr[
"name"
] = i.ToString();
dt.Rows.Add(dr);
}
string
str = ConfigurationManager.ConnectionStrings[
"connStr"
].ConnectionString.ToString();
//声明数据库连接
SqlConnection conn =
new
SqlConnection(str);
conn.Open();
//声明SqlBulkCopy ,using释放非托管资源
using
(SqlBulkCopy sqlBC =
new
SqlBulkCopy(conn))
{
//一次批量的插入的数据量
sqlBC.BatchSize = 1000;
//超时之前操作完成所允许的秒数,如果超时则事务不会提交 ,数据将回滚,所有已复制的行都会从目标表中移除
sqlBC.BulkCopyTimeout = 60;
//設定 NotifyAfter 属性,以便在每插入10000 条数据时,呼叫相应事件。
sqlBC.NotifyAfter = 10000;
sqlBC.SqlRowsCopied +=
new
SqlRowsCopiedEventHandler(OnSqlRowsCopied);
//设置要批量写入的表
sqlBC.DestinationTableName =
"dbo.text"
;
//自定义的datatable和数据库的字段进行对应
sqlBC.ColumnMappings.Add(
"id"
,
"tel"
);
sqlBC.ColumnMappings.Add(
"name"
,
"neirong"
);
//批量写入
sqlBC.WriteToServer(dt);
}
conn.Dispose();
Response.Write(
"<br/>"
);
DateTime endTime = DateTime.Now;
Response.Write(
"结束时间:"
+ endTime.ToString(
"yyyy年MM月dd日:HH:mm:ss:fff"
));
TimeSpan useTime = endTime-beginTime;
//使用时间
Response.Write(
"<br/>插入时间:"
+ useTime.TotalSeconds.ToString()+
"秒"
);
}
//响应时事件
void
OnSqlRowsCopied(
object
sender, SqlRowsCopiedEventArgs e)
{
Response.Write(
"<br/> OK! "
);
}
----------------------------------------------------------------
在做大批量数据插入的时候,如果用Insert into ... values (...)这种方式的话效率极低,这里介绍两种性能比较好的批量插入方法。
1. 使用SqlBulkCopy
private static long SqlBulkCopyInsert()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
DataTable dataTable = GetTableSchema();
string passportKey;
for (int i = 0; i < count; i++)
{
passportKey = Guid.NewGuid().ToString();
DataRow dataRow = dataTable.NewRow();
dataRow[0] = passportKey;
dataTable.Rows.Add(dataRow);
}
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(connectionString);
sqlBulkCopy.DestinationTableName = "Passport";
sqlBulkCopy.BatchSize = dataTable.Rows.Count;
SqlConnection sqlConnection = new SqlConnection(connectionString);
sqlConnection.Open();
if (dataTable!=null && dataTable.Rows.Count!=0)
{
sqlBulkCopy.WriteToServer(dataTable);
}
sqlBulkCopy.Close();
sqlConnection.Close();
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
使用SqlBulkCopy类进行数据插入其原理是采用了SQL Server的BCP协议进行数据的批量复制。这里我们先要建好一个DataTable(最好是通过DataAdapter来灌数据得到,因为这样出来的DataTable就已经有跟数据表相同的列定义,可以免去之后Mapping Column的步骤),把要插入的数据加进这个DataTable中,然后用SqlBulkCopy的实例来插入到数据库中。经过测试,SqlBulkCopy方法比直接用Sql语句插入数据的效率高出将近25倍。
另外批量导入SQL、MYSQL等数据是同样的for循环,使用拼出来的sql或者使用参数的方式传递或者使用事务等不同方式的传递效率都不同。如果不使用SqlBulkCopy的方式的话,我测试下来做快递是用一次事务来操作为最快。因为10000次的循环如果是每次提交,那么都有链接和停止数据库的操作,或者说他包含了1000次的小事务处理。如果外面就一个事务的话效率肯定会高。
#1楼 绝代恭敬 2010-07-12 20:14
using(SqlBulkCopy sbc = new SqlBulkCopy(connString))
{
try
{
sbc.DestinationTableName =ObjectName;
sbc.WriteToServer(dt);
}
catch(Exception ex)
{
throw new DataAccessException("BulkInsert调用异常", ex);
}
}
-----------------------------------------------------
SqlBulkCopy使用心得
最近做的项目由于之前的设计人员懒省事,不按照范式来,将一张表的扩展信息存到了一个“键-值”表中。如下图:
对于主表中的每一条信息,大约有60个“key”,也就是说主表中每插入1条记录,子表中必须要插入60条。
通过预估我们确定主表中最终的数据量大约是20万,也就是说,子表中会有20x60=1200万条记录。同样类型的“主-子”表我们一共有4对,且不说这些表的查询效率,单是每天一次的数据导入对于我们来说就是一项巨大的挑战。
在此我吐槽一下,本来一个十万级的数据库,就是让这种垃圾“设计师”生生给搞成了个千万级的。而且最初他提出的数据插入方案是将每一条数据都生成一条Insert语句,然后逐条调用ExecuteNoQuery执行,后果就是测试用的3000条主表记录,共生成3000x60x4=72万条数据,花费7小时执行完毕,性能30条/秒。后来他辞职了,换了个人,然后第二任也辞职了,第三任就是在下。
项目到我手里之后,在我的坚持下重新进行了软件结构设计,由于数据库系统已经被另一个子系统使用,所以没办法更改了,只好去寻找一种高效的插入方式。
最开始我使用多线程,开10个线程,使性能提升到300条/秒,测试用记录花费大约40分钟插入完毕,对于多60倍的正式数据来说,40小时执行完毕显然不能满足我们每天一次数据导入工作的要求。
通过Google大神,我找到了SqlBulkCopy。
经过测试,性能我很满意,4000条/秒,那就先用它吧,下一阶段的工作重点就是干掉“键-值”表。
在使用中,我也碰到了一些“莫名其妙”的问题,在此记下,以备查询。
- SqlBulkCopy可以将一个DataTable对象插入到指定名称的数据表中,但是,这个DataTable的架构必须和数据库表一样,尤其要注意一点,DataTable中列的顺序必须和数据库表一样,而且不允许间隔。比如:数据库表中有A、B、C三列,其中B列有默认值,这时用于插入的DataTable不能只有A、C两列,如果只有这两列,就会把DataTable里C列的数据插入数据库表B列里,而把DBNull插入C列里。如果是C列有默认值,DataTable可以只有A、B两列。
- SqlBulkCopu的默认超时时间是30秒,30x4000=1.2万,无法满足我一次性插入单张表的需要,改成3600秒。
SqlBulkCopy批量插入数据相关推荐
- sqlserver:使用 SqlBulkCopy 批量插入数据
环境: window 10 sqlserver 2014 参考: <博文:SqlBulkCopy使用注意事项> 1. 问题场景 在批量迁移或导入数据时,我们可能会遇到插入大量数据的问题,比 ...
- C#使用SqlTransaction事务回滚与SqlBulkCopy批量插入数据
C#中批量处理数据,有时候因为一条记录导致整个批量处理失败.这时候肯能会导致数据不全等问题,这时候我们可以使用SqlTransaction来进行事务回滚,即是要么全部成功要么全部不成功.如下代码 // ...
- bulkwrite 批量插入_使用SqlBulkCopy批量插入数据
static void Main(string[] args) {//定义与目标表结构相同的DataTable DataTable dataTable = newDataTable(); dataTa ...
- SQL Server 批量插入数据方案 SqlBulkCopy 的简单封装,让批量插入更方便
在线工具 一.Sql Server插入方案介绍 关于 SqlServer 批量插入的方式,有三种比较常用的插入方式,Insert.BatchInsert.SqlBulkCopy,下面我们对比以下三种方 ...
- SQLServer中批量插入数据方式的性能对比 (转)
转自:http://www.cnblogs.com/wlb/archive/2010/03/02/1676136.html 昨天下午快下班的时候,无意中听到公司两位同事在探讨批量向数据库插入数据的性能 ...
- SQLServer 批量插入数据的两种方法
SQLServer 批量插入数据的两种方法- 发布:dxy 字体:[增加 减小] 类型:转载 在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用In ...
- SQLServer中批量插入数据方式的性能对比
昨天下午快下班的时候,无意中听到公司两位同事在探讨批量向数据库插入数据的性能优化问题,顿时来了兴趣,把自己的想法向两位同事说了一下,于是有了本文. 公司技术背景:数据库访问类(xxx.DataBase ...
- 三种批量插入数据的方法
批量插入数据 本文将介绍三种批量插入数据的方法.第一种方法是使用循环语句逐个将数据项插入到数据库中:第二种方法使用的是SqlBulkCopy,使您可以用其他源的数据有效批量加载 SQL Server ...
- sql server 使用SqlBulkCopy批量插入数据库
sql server sqlbulkcopy 批量数据插入数据库使用的是System.Data.SqlClient中的 SqlBulkCopy批量数据插入数据库 sql server 使用SqlBul ...
最新文章
- 你有哪些深度学习(rnn、cnn)调参的经验?
- java数据安全_java数据安全(一)
- Shell环境变量以及set,env,export的区别
- linux命令deploy_linux命令:du 命令
- jqgrid删除某一列(隐藏)
- win10怎么把c盘锁住_老司机教你win10下怎么清理c盘
- ArcGIS制图技巧系列(3)—让地图更有立体感
- 我敢打赌,你对ConcurrentHashMap不了解?
- python excel 填充颜色_“利用python将图填充到excel案例”
- 阿里资深技术专家:35岁IT职场人的8个经验总结!
- php background,CSS BACKGROUND定位背景上下左右偏移
- 混沌数学之Henon吸引子
- MySQL 8 复制(一)——异步复制
- C# 插入或删除word分页符
- Python--pyaudio声卡录音
- vue项目架构搭建-3
- linux下三台虚拟机互联,Linux下虚拟机qemu的使用
- 猿辅导2019 编程两道
- Python不换行输出
- 手机黑名单,拦截电话和短信,清除通话记录