【转载】C#批量插入数据到Sqlserver中的三种方式
引用:https://m.jb51.net/show/99543
本篇,我将来讲解一下在Sqlserver中批量插入数据。
先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引。GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记录的ID的值然后再进行加1运算要少。而如果存在索引的情况下,每次插入记录都会进行索引重建,这是非常耗性能的。如果表中无可避免的存在索引,我们可以通过先删除索引,然后批量插入,最后再重建索引的方式来提高效率。
create database CarSYS;
go
use CarSYS;
go
CREATE TABLE Product(
Id UNIQUEIDENTIFIER PRIMARY KEY,
NAME VARCHAR(50) NOT NULL,
Price DECIMAL(18,2) NOT NULL
)
我们通过SQL脚本来插入数据,常见如下三种方式。
方式一,一条一条插入,性能最差,不建议使用。
INSERT INTO Product(Id,Name,Price) VALUES(newid(),'牛栏1段',160);
INSERT INTO Product(Id,Name,Price) VALUES(newid(),'牛栏2段',260);
......
方式二
INSERT INTO Product(Id,Name,Price) VALUES
(newid(),'牛栏1段',160)
,(newid(),'牛栏2段',260)
......
方式三
INSERT INTO Product(Id,Name,Price)
SELECT NEWID(),'牛栏1段',160
UNION ALL
SELECT NEWID(),'牛栏2段',180
UNION ALL
......
在C#中通过ADO.NET来实现批量操作同样也存在三种方式。
方式一:逐条插入
static void InsertOne()
{
Console.WriteLine("采用一条一条插入的方式实现");
Stopwatch sw = new Stopwatch();
long totalRow = 1000000; using (SqlConnection conn = new SqlConnection(StrConnMsg)) //using中会自动Open和Close 连接。
{
string sql = "INSERT INTO Product(Id,Name,Price) VALUES(newid(),@p,@d)";
conn.Open();
for (int i = 0; i < 1000000; i++)
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{ cmd.Parameters.AddWithValue("@p", "商品" + i);
cmd.Parameters.AddWithValue("@d", i);
sw.Start();
cmd.ExecuteNonQuery(); Console.WriteLine(string.Format("插入1条记录,时间:{0}", sw.ElapsedMilliseconds));
}
if (i == 1000)
{
sw.Stop();
break;
}
}
}
Console.WriteLine(string.Format("插入{0}条记录,每1000条的插入时间是{1}毫秒,预估总得插入时间是{2}毫秒,{3}分钟", totalRow, sw.ElapsedMilliseconds,
((sw.ElapsedMilliseconds / 1000) * totalRow), GetMinute((sw.ElapsedMilliseconds / 1000 * totalRow))));
}
运行结果如下:

我们会发现插入100w条记录,预计需要50分钟时间,每插入一条记录大概需要3毫秒左右。
方式二:使用SqlBulk
#region 方式二
static void InsertTwo()
{
Console.WriteLine("使用Bulk插入的实现方式");
Stopwatch sw = new Stopwatch();
DataTable dt = GetTableSchema(); using (SqlConnection conn = new SqlConnection(StrConnMsg))
{
SqlBulkCopy bulkCopy = new SqlBulkCopy(conn);
bulkCopy.DestinationTableName = "Product";
bulkCopy.BatchSize = dt.Rows.Count;
conn.Open();
sw.Start(); for (int i = 0; i < totalRow;i++ )
{
DataRow dr = dt.NewRow();
dr[0] = Guid.NewGuid();
dr[1] = string.Format("商品", i);
dr[2] = (decimal)i;
dt.Rows.Add(dr);
}
if (dt != null && dt.Rows.Count != 0)
{
bulkCopy.WriteToServer(dt);
sw.Stop();
}
Console.WriteLine(string.Format("插入{0}条记录共花费{1}毫秒,{2}分钟", totalRow, sw.ElapsedMilliseconds, GetMinute(sw.ElapsedMilliseconds)));
}
}
static DataTable GetTableSchema()
{
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[] {
new DataColumn("Id",typeof(Guid)),
new DataColumn("Name",typeof(string)),
new DataColumn("Price",typeof(decimal))});
return dt;
}
#endregion
运行结果如下:

插入100w条记录才8s多,是不是很溜。
方式三:使用TVPs(表值参数)插入数据
从sqlserver 2008起开始支持TVPs。创建缓存表ProductTemp ,执行如下SQL。
CREATE TYPE ProductTemp AS TABLE(
Id UNIQUEIDENTIFIER PRIMARY KEY,
NAME VARCHAR(50) NOT NULL,
Price DECIMAL(18,2) NOT NULL
)
执行完成之后,会发现在数据库CarSYS下面多了一张缓存表ProductTemp

可见插入100w条记录共花费了11秒多。
总结:大数据批量插入方式一尽量避免使用,而方式二和方式三都是非常高效的批量插入数据方式。其都是通过构建DataTable的方式插入的,而我们知道DataTable是存在内存中的,所以当数据量特别特别大,大到内存中无法一次性存储的时候,可以分段插入。比如需要插入9千万条数据,可以分成9段进行插入,一次插入1千万条。而在for循环中直接进行数据库操作,我们是应该尽量避免的。每一次数据库的连接、打开和关闭都是比较耗时的,虽然在C#中存在数据库连接池,也就是当我们使用using或者conn.Close(),进行释放连接时,其实并没有真正关闭数据库连接,它只是让连接以类似于休眠的方式存在,当再次操作的时候,会从连接池中找一个休眠状态的连接,唤醒它,这样可以有效的提高并发能力,减少连接损耗。而连接池中的连接数,我们都是可以配置的。
源码下载:https://pan.baidu.com/s/1slKrrLr
【转载】C#批量插入数据到Sqlserver中的三种方式的更多相关文章
- C#批量插入数据到Sqlserver中的三种方式
本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生 成 ...
- C#批量插入数据到Sqlserver中的四种方式
我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...
- C#_批量插入数据到Sqlserver中的四种方式
先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...
- C#批量插入数据到Sqlserver中的四种方式 - 转
先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...
- C# 之 批量插入数据到 SQLServer 中
创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快.而如果存在索引的情况下,每次插入记录都会进行索引重建,这是非常耗性能的.如 ...
- sql 批量插入数据到Sqlserver中 效率较高的方法
使用SqlBulk #region 方式二 static void InsertTwo() { Console.WriteLine("使用Bulk插入的实现方式"); Stopwa ...
- 用SqlBulkCopy批量插入数据到SqlServer数据库表中
首先创建一个数据库连接类:SQLHelper using System; using System.Collections.Generic; using System.Linq; using Syst ...
- .Net批量插入数据到SQLServer数据库,System.Data.SqlClient.SqlBulkCopy类批量插入大数据到数据库
批量的的数据导入数据库中,尽量少的访问数据库,高性能的对数据库进行存储. 采用SqlBulkCopy来处理存储数据.SqlBulkCopy存储大批量的数据非常的高效,将内存中的数据表直接的一次性的存储 ...
- Ajax上传数据和上传文件(三种方式)
Ajax向后端发送数据可以有三种方式:原生Ajax方式,jQuery Ajax方式,iframe+form 方式(伪造Ajax方式) <!DOCTYPE html> <html la ...
随机推荐
- git 突破大文件上传限制
1.安装 lfs: git lfs install 2.跟踪大文件:git lfs track "file.suffix" 3.添加配置文件:git add .gitattribu ...
- html table 的属性
表格table th,td 文字顶部对齐 <th valign="top"></th> <td valign="top">& ...
- 转:ACCESS数据库转ORACLE数据库分享
来源: 作者:zz 网上有很多文章介绍access转oracle数据库的方法,本人都尝试了,不是很成功,列举一下,后来人不必盲目试了,基本不成功: 1.Access-->excel-->P ...
- Python基础学习之字符串(1)
字符串 由字符组成的序列,即字符串. 1.基本字符串操作 所有标准的序列操作(索引.切片.乘法.判断成员资格.求长度.取最小值和最大值)对字符串同样适用: >>> website=' ...
- PHP文件是什么?如何打开PHP文件?
在平时我们可能会碰到过php文件,可是很多用户不知道php文件是什么文件?也不知道怎么打开php文件?为了满足一些用户的好奇心,小编现在就给大家讲解php文件以及如何打开php文件的方法. 1.PHP ...
- 初识Python(四)
一.数字数据类型 Python的数字数据类型用于存储数值,它是不可变的数据类型,这意味着改变数字数据类型,则需要一个新分配的对象: Python支持四种不同的数值类型: 整型(Int):通常被称为是整 ...
- 计算后缀表达式的过程(C#)
计算后缀表达式的过程是一个很好玩的过程,而且很简单哦!这里呢,有个计算的技巧,就是:遇到数字直接入栈,遇到运算符就计算! 后缀表达式也叫逆波兰表达式,求值过程可以用到栈来辅助存储: 假定待求值的后缀表 ...
- 前端高质量知识(二)-JS执行上下文(执行环境)详细图解Script
先随便放张图 我们在JS学习初期或者面试的时候常常会遇到考核变量提升的思考题.比如先来一个简单一点的. console.log(a); // 这里会打印出什么? var a = 20; PS: 变量提 ...
- 【转】Android 组件系列-----Activity保存状态
本篇随笔将详细的讲解Activity保存状态的概念,也就是saving activity state. 一.Activity状态保持概念 保存Activity的状态是非常重要的,例如我们在玩一个游戏的 ...
- Annual Congress of MUD(最大流)
Annual Congress of MUD 时间限制: 1 Sec 内存限制: 128 MB提交: 80 解决: 10[提交] [状态] [讨论版] [命题人:admin] 题目描述 Multi ...