sqlserver:使用 SqlBulkCopy 批量插入数据
环境:
- window 10
- sqlserver 2014
参考:
《博文:SqlBulkCopy使用注意事项》
1. 问题场景
在批量迁移或导入数据时,我们可能会遇到插入大量数据的问题,比如:100万、500万、甚至几千万。
这个时候,如果我们再使用普通的insert插入的话就太慢了。
在sqlserver中,我们可以使用 SqlBulkCopy 进行大数据量的插入。
2. 简单示例
先看个示例:
var connString = "Data Source=192.168.252.129;Initial Catalog=test;User ID=sa;Password=123456;Encrypt=True; TrustServerCertificate=True;";
var conn = new SqlConnection(connString);
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandText = @"create table test(
id int primary key,
name varchar(50)
)";
cmd.ExecuteNonQuery();
var dt = new DataTable("test");
dt.Columns.Add("id");
dt.Columns.Add("name");
for (var i = 0; i < 5; i++)
{var row = dt.NewRow();row["id"] = i;row["name"] = "name" + i;dt.Rows.Add(row);
}var sbc = new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, null);
sbc.DestinationTableName = dt.TableName;for (int i = 0; i < dt.Columns.Count; i++)
{sbc.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName);
}
sbc.WriteToServer(dt);
conn.Close();
插入的数据如下:
3. 注意点
上面是一个简单的示例,我们在使用的时候需要关注以下几种情况:
- 如果上面表的id是自增的话,那么批量插入时是数据库自增还是使用自己指定的?(
SqlBulkCopyOptions.KeepIdentity
); - 如果上面表的某列有定义默认值,那么批量插入数据时是使用定义的默认值还是自己指定数据的null值?(
SqlBulkCopyOptions.KeepNulls
); - 如果上面表的某列有检查约束,那么批量插入时,是否进行检查以保证数据正确?(
SqlBulkCopyOptions.CheckConstraints
); - 如果上面表定义了insert触发器,那么批量插入数据时,是否触发?(
SqlBulkCopyOptions.FireTrigger
); - 插入时是否内部开启一个事务,以保证数据完整性?(
SqlBulkCopyOptions.UseInternalTransaction
); - 插入时是否获取这个表的表锁(默认是行锁)?(
SqlBulkCopyOptions.TableLock
);
上面的这些设置使用如下:
var sbc = new SqlBulkCopy(conn, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.KeepNulls null);
上面的配置项,建议取SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.KeepNulls
,
因为在批量插入数据时我们是希望将自己准备的树原封不动的插入进去!!!
另外,我们需要注意,当我们使用SqlBulkCopyOptions.UseInternalTransaction
选项的时候,我们不能再手动指定事务,否则会报错:
除了上面的参数,还有一个需要关注的,就是执行超时时间,默认是30秒,如果数据量太大,可以设置的长一点,如下:
var sbc = new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, null);
sbc.DestinationTableName = dt.TableName;
sbc.BulkCopyTimeout = 60 * 30;//半小时
4. 性能测试
下面以测试插入500万条数据耗时结束本次实验:
public static void Main(string[] args){var connString = "Data Source=192.168.252.129;Initial Catalog=test;User ID=sa;Password=123456;Encrypt=True; TrustServerCertificate=True;";var conn = new SqlConnection(connString);conn.Open();var cmd = conn.CreateCommand();cmd.CommandText = @"create table test(
id int primary key,
name varchar(50),
age int,
addr varchar(50),
birth datetime,
avatar varchar(500),
sex int,
uno varchar(50),
remark varchar(50)
)";cmd.ExecuteNonQuery();var st = new Stopwatch();st.Start();var dt = new DataTable("test");dt.Columns.Add("id");dt.Columns.Add("name");dt.Columns.Add("addr");dt.Columns.Add("birth");dt.Columns.Add("avatar");dt.Columns.Add("sex");dt.Columns.Add("uno");dt.Columns.Add("remark");var count = 500 * 10000;for (var i = 0; i < count; i++){var row = dt.NewRow();row["id"] = i;row["name"] = "name" + i;row["addr"] = "天明路" + i;row["birth"] = DateTime.Now.AddMilliseconds(i);row["avatar"] = $"http://www.qq.com/1234567878/{i + 1}.png";row["sex"] = i % 2;row["uno"] = Guid.NewGuid().ToString();row["remark"] = $"这是一个关于{i} 的描述!";dt.Rows.Add(row);}Console.WriteLine($"准备数据: 500万,花费: {st.ElapsedMilliseconds} 毫秒!");st.Restart();var sbc = new SqlBulkCopy(conn, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.KeepNulls, null);sbc.DestinationTableName = dt.TableName;//向服务器传输,一次传输1万条sbc.BatchSize = 10000;sbc.SqlRowsCopied += (object sender, SqlRowsCopiedEventArgs e) =>{Console.WriteLine($"已拷贝: {e.RowsCopied} 行,进度: {(e.RowsCopied / (count + 0.0) * 100).ToString("0.00")}%");};//进度通知: 没传输1万条回调一次 SqlRowsCopiedsbc.NotifyAfter = 10000;sbc.BulkCopyTimeout = 5 * 60;//5分钟超时for (int i = 0; i < dt.Columns.Count; i++){sbc.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName);}sbc.WriteToServer(dt);conn.Close();st.Stop();Console.WriteLine($"插入数据: 500万,花费: {st.ElapsedMilliseconds} 毫秒!");Console.ReadLine();}
输出如下:
sqlserver:使用 SqlBulkCopy 批量插入数据相关推荐
- SqlBulkCopy批量插入数据
利用SqlBulkCopy快速大批量导入数据 protected void Button1_Click(object sender, EventArgs e) { DateTime ...
- C#使用SqlTransaction事务回滚与SqlBulkCopy批量插入数据
C#中批量处理数据,有时候因为一条记录导致整个批量处理失败.这时候肯能会导致数据不全等问题,这时候我们可以使用SqlTransaction来进行事务回滚,即是要么全部成功要么全部不成功.如下代码 // ...
- bulkwrite 批量插入_使用SqlBulkCopy批量插入数据
static void Main(string[] args) {//定义与目标表结构相同的DataTable DataTable dataTable = newDataTable(); dataTa ...
- SQLServer 批量插入数据的两种方法
SQLServer 批量插入数据的两种方法- 发布:dxy 字体:[增加 减小] 类型:转载 在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用In ...
- SQL Server 批量插入数据方案 SqlBulkCopy 的简单封装,让批量插入更方便
在线工具 一.Sql Server插入方案介绍 关于 SqlServer 批量插入的方式,有三种比较常用的插入方式,Insert.BatchInsert.SqlBulkCopy,下面我们对比以下三种方 ...
- SQLServer中批量插入数据方式的性能对比 (转)
转自:http://www.cnblogs.com/wlb/archive/2010/03/02/1676136.html 昨天下午快下班的时候,无意中听到公司两位同事在探讨批量向数据库插入数据的性能 ...
- SQLServer使用表值参数,高性能批量插入数据
记得前段时间帮同事写了个解析账号并入库的小工具,来批量导入账号信息,账号量相当大,程序每读取一条记录便执行一次insert来插入数据,整整跑了一下午才把账号全部入库. 今天又接到同事类似的需求,不过这 ...
- SQLServer中批量插入数据方式的性能对比
昨天下午快下班的时候,无意中听到公司两位同事在探讨批量向数据库插入数据的性能优化问题,顿时来了兴趣,把自己的想法向两位同事说了一下,于是有了本文. 公司技术背景:数据库访问类(xxx.DataBase ...
- sql server 使用SqlBulkCopy批量插入数据库
sql server sqlbulkcopy 批量数据插入数据库使用的是System.Data.SqlClient中的 SqlBulkCopy批量数据插入数据库 sql server 使用SqlBul ...
最新文章
- Yahoo中国变脸?
- 运算符重载,以及迭代器[foreach]示例
- linux怎么查看一个文件夹的大小
- mysql忘记root密码咋办_MySQL忘记root用户密码怎么办?
- 元璟资本陈洪亮解析人货场融合 消费者变成“合作者”
- 【python爬虫】报错module requests has no attribute get
- 安卓学习笔记29:使用SQLite数据库
- 使用string定义一个变量如何输出
- Ubuntu firefox 显示在运行无法打开,如何在终端关闭进程
- 保存OpenCV中Mat_Vec3f格式的图像
- “产品助理最重要的工作是 Android 版本的设计与测试”
- 让Android虚拟手机快速启动
- 阿里这份Java程序性能优化指南,让你的程序快上200%
- 组态王五层电梯c语言编程,PLC编程实例分享,多图详解五层楼电梯控制系统~...
- android 颜色自动变淡,android 颜色值变化小解
- 面试备战笔记2019
- android ssl双向验证 X509证书信任管理器类的实现及应用
- android 多个sdcard路径,Android中访问sdcard路径的几种方式
- 解析春运玄学:携程飞猪去哪儿们的抢票加速包,到底灵不灵?
- VS code 代码鼠标滑轮缩放
热门文章
- 【SDK】Agora主服务创建及RTE login RTM操作
- 【常用运维技巧】Linux文件创建的N种方法
- Solidity 中 receive 函数 和 callback函数分析
- Unity中实现Scene模式下的鼠标操作效果
- 【转自MOP】由骂Iphone的一个帖子,想到中国离世界的差距有多大?
- 51.计算机通电后自动开机,Win10专业版怎么解决电脑关机后又自动开机的问题?
- webstorm 代码格式化、查找替换快捷键
- 如何在vue循环列表中实现点赞改变icon和字体颜色,不可取消点赞
- 常用的字符串截取方法
- c语言每日签到_C语言socket编程--每日签到