本篇,我将来讲解一下在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(),进行释放连接时,其实并没有真正关闭数据库连接,它只是让连接以类似于休眠的方式存在,当再次操作的时候,会从连接池中找一个休眠状态的连接,唤醒它,这样可以有效的提高并发能力,减少连接损耗。而连接池中的连接数,我们都是可以配置的。

C#批量插入数据到Sqlserver中的三种方式的更多相关文章

  1. 【转载】C#批量插入数据到Sqlserver中的三种方式

    引用:https://m.jb51.net/show/99543 这篇文章主要为大家详细介绍了C#批量插入数据到Sqlserver中的三种方式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本篇, ...

  2. C#批量插入数据到Sqlserver中的四种方式

    我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...

  3. C#_批量插入数据到Sqlserver中的四种方式

    先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...

  4. C#批量插入数据到Sqlserver中的四种方式 - 转

    先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...

  5. C# 之 批量插入数据到 SQLServer 中

    创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快.而如果存在索引的情况下,每次插入记录都会进行索引重建,这是非常耗性能的.如 ...

  6. sql 批量插入数据到Sqlserver中 效率较高的方法

    使用SqlBulk #region 方式二 static void InsertTwo() { Console.WriteLine("使用Bulk插入的实现方式"); Stopwa ...

  7. 用SqlBulkCopy批量插入数据到SqlServer数据库表中

    首先创建一个数据库连接类:SQLHelper using System; using System.Collections.Generic; using System.Linq; using Syst ...

  8. .Net批量插入数据到SQLServer数据库,System.Data.SqlClient.SqlBulkCopy类批量插入大数据到数据库

    批量的的数据导入数据库中,尽量少的访问数据库,高性能的对数据库进行存储. 采用SqlBulkCopy来处理存储数据.SqlBulkCopy存储大批量的数据非常的高效,将内存中的数据表直接的一次性的存储 ...

  9. Ajax上传数据和上传文件(三种方式)

    Ajax向后端发送数据可以有三种方式:原生Ajax方式,jQuery Ajax方式,iframe+form 方式(伪造Ajax方式) <!DOCTYPE html> <html la ...

随机推荐

  1. Spring AOP 由浅入深

    (分析基于Spring的版本:version = 4.1.6.RELEASE) Spring AOP工厂: org.springframework.aop.framework.DefaultAopPr ...

  2. 【解决】SharePoint Foundation 2013 未显示搜索框

    在正确安装 SharePoint Foundation 2013 后会发现页面中缺少搜索框. 经查询网页了解到这是一个Bug,而且在 SP1 中也没有修复,所以即便是安装了 SP1 补丁的系统也需要下 ...

  3. 【解决】AWS服务控制台中上传文件失败

    使用IE 11,在 AWS Services Console 中不管是 S3 还是 Elastic Beanstalk 的页面中上传页面都会失败,提示信息如下: A problem occurred ...

  4. 【解决】SharePoint 2013 当鼠标悬停在用户名称上时页面会崩溃

    参考下面文章,此问题是由于IE中的Office插件版本不正确所致,只需在 控制面板 > 程序和功能 中修复 Office 的安装即可. http://sympmarc.com/2013/11/2 ...

  5. Ajax跨域访问

    Ajax如何跨域访问数据 最近在做项目的过程中遇到的问题,一个网站需要访问另外一个网站的数据,并且是通过脚本的方式,而由于同源策略的限制,开发人员不能再与外部服务器进行通信的时候使用XMLHttpRe ...

  6. PHP开源论坛PunBB在IIS上部署和安装

    说明:对PHP的模式修饰符e来说:自 PHP 5.5.0 起废弃,而PunBB1.4.2还是有用到的(我曾用二者搭配,结果网站运行中会出现错误),所以我用了php-5.4.30. 一.运行环境 首先如 ...

  7. [python实现设计模式]-3.简单工厂模式-触宝开放平台

    预备知识: 开放封闭原则(Open-Closed Principle OCP) Software entities(classes,modules,functions etc) should open ...

  8. 关于android.view.WindowManager$BadTokenException问题出现以及解决的一些记录

    1.出现 在app showdialog()时偶尔会出现,根据stackoverflow.com的描述,貌似是show的时候用作context的activity以及destroy了,,,一些异步操作会 ...

  9. LoadRunner测试结果分析02 转载至zhangzhe的新浪博客

    LoadRunner测试结果分析之我见 上述测试过程的重点在于事务,而LoadRunner生成的测试结果图并不局限于事务上,其中还有是关于Vusers.Errors.Web Resources.Web ...

  10. http请求提交cookie

    package leadsServerTest;import org.apache.http.HttpResponse;import org.apache.http.client.HttpClient ...