【转载】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 ...
随机推荐
- Devexpress Xtrareport 打印报表
需要引用 Using Devexpress.Xtrareport.UI: Using Devexpress.XtraPrinting.Localiztion 实例化报表,xtrareport my=n ...
- sqlserverToXML
--raw模式 以属性的形式展示select * from goods for xml rawselect *from goods for xml raw('goods') --修改节点名称selec ...
- jquery的html()、text()、val()的区别和用法
1.html() html()[无参]的使用方法是获取某元素内部的HTML代码,包括各种标签: 例:句1:<p>不知道大家高考的理综试卷里有没有关于科学家及其成就的选择题</p> ...
- zookeeper的几种使用场景
1.数据的发布与订阅 通过发布与订阅实现配置的信息的统一管理,主要采用zk节点可以存储数据的特性,我们可以将一些配置信息存放到某一节点上,订阅这个节点的服务就可以动态的获取这个节点的数据.在应用启动的 ...
- linux单机限速工具
wondershaper是国外人开发的一款在Linux内核下基于TC工具的对整块网卡的限度工具. http://lartc.org/wondershaper/ 安装wondershaper: [roo ...
- DB2安装教程图解
下载好之后,是exe文件,但是双击后基本上都是解压,但是使用自身的解压的话会有很多文件解压失败的情况,所以推荐使用自己电脑上自带的解压工具直接解压(如360解压,好压等). 解压之后直接运行setup ...
- 爱上python(几个小例子)
1.任务:简单测试局域网中的网络是否连接,ip范围:192.168.2.101到192.168.2.200. python 实现代码: import subprocess cmd="cmd. ...
- 笨办法学Python(三十三)
习题 33: While 循环 接下来是一个更在你意料之外的概念: while-loop``(while 循环).``while-loop 会一直执行它下面的代码片段,直到它对应的布尔表达式为 Fal ...
- Linux修改文件permission可执行属性
列出文件属性 ls -al 修改文件属性为可读.可写 sudo chmod -c 777 <your file name>
- frame、window和dialog区别
属性 Window Frame Dialog 模式化 不是 不是 不是(可设置) 可调大小 不可 可 可 标题栏 无 有 有 边界 无 有 有 标题 无 有 有 菜单栏 无 有 无 焦点管理器 有 有 ...