Sql Server海量数据插入(BULK INSERT 执行数据文件)_sql server bulk insert-程序员宅基地

技术标签: a  Sql Server  SqlServer  大数据  

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 = 1;
    while (i <= 500000)
    {
       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 = 1;
            while (i <= 500000)
            {
                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 = 1;
            while (i <= 500000)
            {
                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 = 1;
            while (i <= 500000)
            {
                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 = 0;
            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多分钟

 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hezhixiang/article/details/81098411

智能推荐

【MATLAB】一种偶然性更小的抽奖代码-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏4次。一种偶然性更小的抽奖代码。由于突发事件,需要进行“抽奖”。大家都怕中奖,所以让我搞一个更“公平”的代码来抽。

ITK-SNAP 安装和使用_itk snp 安装知乎-程序员宅基地

文章浏览阅读7.2w次,点赞23次,收藏139次。一.下载ITK-SNAP 安装包下载资源链接:https://sourceforge.net/projects/itk-snap/?source=directory或者http://www.itksnap.org/pmwiki/pmwiki.php?n=Downloads.SNAP3本人下载的是 ITK-SNAP 3.0 ,ITK-SNAP 3.4 ,ITK-SNAP 3.6 三个..._itk snp 安装知乎

Qt模块化笔记之network——写第一个Tcp程序(1)_signal(hasdata(qbytearray))-程序员宅基地

文章浏览阅读3.8k次。本节以QTcpServer与QTcpSocket为主,联合其它知识(sql与json),编写TCP服务器与客户端,以让读者更好理解Qt的TCP部分各函数功能。程序结构参考自qtcn上的liudianwu的TCP调试工具,原程序链接:点击打开链接。由于是业余爱好者,不知软件公司里这种程序结构,欢迎指点。———————————————————————————————————————————————_signal(hasdata(qbytearray))

jmeter二次开发-程序员宅基地

文章浏览阅读231次。1.下载源码http://jmeter.apache.org/download_jmeter.cgi2.修改文件名eclipse.classpath和eclipse.projectren .\eclipse.classpath .classpathren .\eclipse.project .project3.导入源码到项目4.ant编译build.xml下载依..._org.apache.jmeter.newdriver

Unbuntu ./btest : cannot execute binary file: Exec format error解决方案(CSAPP)_ubuntu cannot execute binary file: exec format err-程序员宅基地

文章浏览阅读2.8k次。用WSL尝试CSAPP的第一个实验碰到的问题:用下面的查了一下文件的类型:file btest然后用各大搜索引擎找到一个类似的问题,原因是unbuntu还不支持32-bit i386 ELF binaries:GitHub上已经有人碰到过这个问题但是似乎还是没有解决,地址:Support for 32-bit i386 ELF binaries解决方案:vim Makefile找到里面的:改为:我的可以用了。不知道是否适用于其它地方,你们如果遇到也可以类试地修改一下。_ubuntu cannot execute binary file: exec format error

局域网或者本地开发https自签名证书解决办法_自签名证书 无域名-程序员宅基地

文章浏览阅读1w次,点赞2次,收藏9次。各种原因,需要使用https,本地开发,没有域名,没法申请免费证书,各种方法,总有大神出现。分享一位大神的一个方法。macOSbrew install mkcertbrew install nss # if you use Firefoxor MacPortssudo port selfupdatesudo port install mkcertsudo port install ..._自签名证书 无域名

随便推点

媒体查询表达式的使用方法-程序员宅基地

文章浏览阅读666次。语法@media 设备类型 and (设备特性){样式}制定设备的值设备类型all所有设备screen电脑显示器print打印用纸或者打印预览视图handheld便携设备tv电视类型设备speech语音和音频合成器braille盲人用点字法触觉回馈设备embossed盲文打印机projection各种投影..._媒体查询表达式

vue控制只能输入小数点和数字,兼容火狐和IE浏览器。而且限制只能输入6位整数和2位小数_vue 限定六位小数-程序员宅基地

文章浏览阅读813次。-----输入框------<el-form-item label="工作时长(小时):" prop="worktimelong" > <el-input v-model="handleform.worktimelong" placeholder="请输入工作时长" /></el-form-item>-----监听------..._vue 限定六位小数

计算思维与创新设计_计算及设计思维-程序员宅基地

计算思维是一种科学思维方式,通过数学和物理的推理和实践思维来进行思考和理解。它使用计算机科学调整整体流程和各个结构,以优化整体效果。点线面解构是计算思维的重要思维模式,通过将问题分解为最小粒度的单元,通过功能点之间的关系来解决整个问题。举例来说,硕士论文主要改变结构,而博士论文则主要改变参数。

关于NetBeans生成可执行exe文件_netbeans可执行文件-程序员宅基地

文章浏览阅读2.6k次。在网上看了很多有关的有用的文章,给大家参考一下1.https://netbeans.org/kb/docs/java/native_pkg_zh_CN.html(NetBeans IDE 中的本机打包(netbeans 官网))结果是生成可安装的程序,就像大家平时安装软件那样,安装后是一个文件夹里面有很多东西,个人觉得不如直接生成exe文件,如22.https://blog.csdn.ne..._netbeans可执行文件

JAR包与描述对照表-程序员宅基地

文章浏览阅读131次。JAR包与描述对照表注:jar包尾后的版本号不代表当前最高版本activation-1.1.jarSun的JavaBeans Activation Framework(JAF),JavaMail要运行必须依赖于它的支持asm-3.0.jar asm-commons-2.2.3.jar asm-util-2.2.3.jarasm是一个轻量级字节码处理和分析框架..._61.0 对应着jar几?

OpenCV-Python图像处理:图像缩放与插值方法及使用resize函数_图像处理缩放中-程序员宅基地

文章浏览阅读427次。OpenCV-Python图像处理:图像缩放与插值方法及使用resize函数图像缩放是图像处理中常见的操作之一,它可以改变图像的大小,从而适应不同的需求和应用场景。在OpenCV-Python中,可以使用resize函数来实现图像缩放操作。本文将介绍图像缩放的概念、常用的插值方法以及如何使用resize函数进行图像缩放。_图像处理缩放中

推荐文章

热门文章

相关标签