目录

1.前言

2.BULK INSERT

3.简单示例

前言

  由于昨天接到一个客户反馈导出数据卡死的问题,于是决定今天模拟一下千万级的数据,然后傻傻的等待插入数据了半天......

  对于海量数据,上百万上千万的数据插入,我们用ADO.NET提供的普通一条一条数据插入非常非常慢,好在Sql Server为我们提供了批量插入方法。

BULK INSERT

  语法

  

  主要参数说明

  database_name

  指定的表或视图所在的数据库的名称,如果未指定,则默认为当前数据库。

  schema_name

  表或视图架构的名称。

  table_name

  要将数据大容量导入其中的表或视图的名称。

  ‘data_file’

  数据文件的完整路径,该数据文件包含到导入到指定表或视图中的数据。使用BULK INSERT可以从磁盘导入数据。

  BATCHSIZE=batch_size

  指定批量处理中的行数。每个批处理作为一个事物复制到服务器。

  CHECK_CONSTRAINTS
      指定在大容量导入操作期间,必须检查所有对目标表或视图的约束。

  FIELDTERMINATOR ='field_terminator'
  指定要用于 char 和 widechar 数据文件的字段终止符,即字段的分隔符。 默认的字段终止符是 \t(制表符)。

  ROWTERMINATOR ='row_terminator'
  指定要用于 char 和 widechar 数据文件的行终止符,即行的分隔符。

  

  更多参数说明,请参考: https://msdn.microsoft.com/zh-cn/library/ms188365.aspx

简单示例

  为了对比BULK INSERT和普通逐条插入的差异,我们通过一个简单的示例,通过实际运行来查看效果。  

  第一步:在数据库新建两张一样的表,分表为Student和Student1,表结构完全相同,只有ID,NAME,AGE三个简单的字段。

  

  第二步:新建一个控制台程序,通过一个简单的循环,生成500000条数据写入到txt文件中,关键代码如下:  

 /// <summary>
/// 生成测试数据
/// </summary>
private static void GenerateTestData()
{
string fileName = "sql"; int i = ;
while (i <= )
{
string strInsert = string.Format("{0},'test{0}',{0}|", i);
File.AppendText(strInsert, fileName);
i++;
}
}

  第三步:封装出两个方法,分别用来执行批量插入和普通插入,具体代码如下:

/// <summary>
/// 批量插入测试
/// </summary>
private static void BulkInsertTest()
{
string strFilePath = @"D:\学习\ASP.NET\QYH.BlukInsertTest\sql.txt";
string strTableName = "Student"; /* 每一个字段的信息以“,”分割
*每一条数据以“|”符号分隔
* 每10万条数据一个事务*/
string sql = string.Format("BULK INSERT {0} FROM '{1}' WITH (FIELDTERMINATOR = ',',ROWTERMINATOR ='|',BATCHSIZE = 50000)", strTableName, strFilePath);
DBHelper dbHelper = new DBHelper();
dbHelper.Excute(sql); } /// <summary>
/// 普通插入测试
/// </summary>
private static void CommonInsertTest()
{
int i = ;
while (i <= )
{
string sqlInsert = string.Format("insert into Student1(id,Name,Age) values({0},'test{0}',{0})", i);
new DBHelper().Excute(sqlInsert);
i++;
}
}

  第四步:Main主函数中调用批量插入和普通插入方法,并通过Stopwatch计算出执行时间,Pragram完整代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using QYH.BlukInsertTest.FileMange;
using QYH.BlukInsertTest.DataBase;
using System.Diagnostics; namespace QYH.BlukInsertTest
{
class Program
{
static void Main(string[] args)
{
//用于生成海量数据
//GenerateTestData(); Stopwatch stopwatch = Stopwatch.StartNew();
try
{
BulkInsertTest();
}
catch (Exception)
{ //throw;
} stopwatch.Stop();
string strResult = "批量插入耗时:" + stopwatch.ElapsedMilliseconds.ToString(); Stopwatch stopwatch1 = Stopwatch.StartNew();
CommonInsertTest();
stopwatch1.Stop();
string str1Result = "普通插入耗时:" + stopwatch1.ElapsedMilliseconds.ToString(); string strTestResult = "result";
File.WriteTextAsync(strResult + "\r\n" + str1Result, strTestResult); //Console.Read();
} /// <summary>
/// 批量插入测试
/// </summary>
private static void BulkInsertTest()
{
string strFilePath = @"D:\学习\ASP.NET\QYH.BlukInsertTest\sql.txt";
string strTableName = "Student"; /* 每一个字段的信息以“,”分割
*每一条数据以“|”符号分隔
* 每10万条数据一个事务*/
string sql = string.Format("BULK INSERT {0} FROM '{1}' WITH (FIELDTERMINATOR = ',',ROWTERMINATOR ='|',BATCHSIZE = 50000)", strTableName, strFilePath);
DBHelper dbHelper = new DBHelper();
dbHelper.Excute(sql); } /// <summary>
/// 普通插入测试
/// </summary>
private static void CommonInsertTest()
{
int i = ;
while (i <= )
{
string sqlInsert = string.Format("insert into Student1(id,Name,Age) values({0},'test{0}',{0})", i);
new DBHelper().Excute(sqlInsert);
i++;
}
} /// <summary>
/// 生成测试数据
/// </summary>
private static void GenerateTestData()
{
string fileName = "sql"; int i = ;
while (i <= )
{
string strInsert = string.Format("{0},'test{0}',{0}|", i);
File.AppendText(strInsert, fileName);
i++;
}
}
}
}

  示例中还用到两个辅助类,DBHelper.cs和File.cs,由于仅用于演示,所以写的非常简单,其中文件路径是写死的,可以替换成实际路径。

  DBHelper.cs  

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace QYH.BlukInsertTest.DataBase
{
public class DBHelper
{
public string connectionString = "Server=.;Database=QYHDB;User ID=sa;Password=123456;Trusted_Connection=False;"; public void Excute(string sql)
{
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand();
command.CommandTimeout = ;
command.Connection = conn;
command.CommandText = sql;
conn.Open();
command.ExecuteNonQuery();
conn.Close();
}
}
}

   File.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace QYH.BlukInsertTest.FileMange
{
public class File
{
public static string strFilePath = @"D:\学习\ASP.NET\QYH.BlukInsertTest"; public static async void WriteTextAsync(string text, string fileName)
{
using (StreamWriter outputFile = new StreamWriter(strFilePath + @"\" + fileName + ".txt"))
{
await outputFile.WriteAsync(text);
}
} public static void AppendText(string text, string fileName)
{
// Append text to an existing file named "WriteLines.txt".
using (StreamWriter outputFile = new StreamWriter(strFilePath + @"\" + fileName + ".txt",true))
{
outputFile.WriteLine(text);
}
}
}
}

  

  一切准备就绪,开始运行,结果如下:

  

  其中单位为毫秒,从结果我们可以看出BULK INSER插入500000条数据还不需要3秒,而普通逐条插入却需要20多分钟

Sql Server海量数据插入的更多相关文章

  1. SQL Server 批量插入数据的两种方法

    在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致SQL一系统性能问题.下面介绍 SQL Server支持的两种批 ...

  2. SQL Server 批量插入数据的两种方法(转)

    此文原创自CSDN TJVictor专栏:http://blog.csdn.net/tjvictor/archive/2009/07/18/4360030.aspx 在SQL Server 中插入一条 ...

  3. 转:SQL Server 批量插入数据的两种方法

    在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致SQL一系统性能问题.下面介绍SQL Server支持的两种批量 ...

  4. ASP.NET MVC与Sql Server交互, 插入数据

    在"ASP.NET MVC与Sql Server建立连接"中,与Sql Server建立了连接.本篇实践向Sql Server中插入数据. 在数据库帮助类中增加插入数据的方法. p ...

  5. sql server不要插入大数据,开销太大

    sql server或者说关系型数据库中不要做一个字段存储大数据量的设计,比如要插入3000w条数据,然后每条数据中有一个文章字段,这个字段每条大概都需要存储几m的数据,那么算下来这个表就得有几百个G ...

  6. SQL Server返回插入数据的ID和受影响的行数

    首先看看数据库里面的数据(S_Id为自增长标识列): sql server 中返回上一次插入数据的ID(标识值)有三种方式: 第一种 @@IDENTITY: insert into Student(S ...

  7. SQL Server 批量插入数据方案 SqlBulkCopy 的简单封装,让批量插入更方便

    一.Sql Server插入方案介绍 关于 SqlServer 批量插入的方式,有三种比较常用的插入方式,Insert.BatchInsert.SqlBulkCopy,下面我们对比以下三种方案的速度 ...

  8. identity in sql server 批量插入history

    https://stackoverflow.com/questions/1920558/what-is-the-difference-between-scope-identity-identity-i ...

  9. 连接sql server、插入数据、从数据库获取时间(C#)

    using System; using System.Data.SqlClient; namespace Test { //连接数据库 public class Connection { privat ...

随机推荐

  1. ORACLE简单触发器

    因工作需要,尝试写一些建议的触发器,下面为其中一例. //创建一个名为TRG_FIN_OPB_ACCOUNTCARD的触发器 create or replace trigger TRG_FIN_OPB ...

  2. Spring+SpringMvc+Mybatis框架集成搭建教程三(框架整合测试程序开发)

    框架整合测试程序开发 (1).在mysql数据库中创建t_user表,sql语句如下 CREATE TABLE `t_user` ( `id` bigint(20) NOT NULL AUTO_INC ...

  3. Centos7设置IP为固定值

    1.进入到系统的IP地址保存文件所在目录 [root@localhost ~]# cd /etc/sysconfig/network-scripts 2.修改保存IP信息的文件 [root@local ...

  4. Android笔记:调试android程序

    1.Debug 第一步: 添加断点 第二步: 右击项目→Debug As→Android Application  //之后一个对话框出现,一会自动消失 第三步: 执行手机端操作,Eclipse 就会 ...

  5. 使用json把php数据传给js处理

    先创建下面的两个文件,并将代码拷贝进去,然后打开json.html文件: json.html文件: <!DOCTYPE html> <html> <head> &l ...

  6. 【MongoDB】 Windows 安装

    Windows下安装MongoDB,虽然网上有很多攻略,但是还是有很多坑,为了以后少犯错误,特此记录. 1.下载安装包 https://fastdl.mongodb.org/win32/mongodb ...

  7. python学习笔记(2)

    1.for循环 用户按照顺序循环可迭代对象中的内容. li = [11,22,33,44] for i in li: print i for循环的else 此功能目前只有for循环里面有发现. 具体条 ...

  8. 11g新特性-查询缓存(1)

    众所周知,访问内存比访问硬盘快得多,除非硬盘体系发生革命性的改变.可以说缓存在Oracle里面无处不在,结果集缓存(Result Cache)是Oracle Database 11g新引入的功能,引入 ...

  9. Tortoise SVN 使用帮助

    同步至本地:新建文件夹,SNV checkout 输入用户名密码,确认. 上传文件:将要上传的文件放在一个文件夹里,选择要上传的文件所在的文件夹,右键单击,tortoiseSVN,Import,选择要 ...

  10. Android想服务器传图片,透过流的方式。还有读取服务器图片(文件),也通过流的方式。

    /** * Created by Administrator on 2016/7/19. */ import android.util.Log; import com.gtercn.asPolice. ...