点滴记录--批量添加数据(千万级)方法-飞外

BULK INSERT 海量添加数据语法

参数说明

database_name

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

schema_name

表或视图架构的名称。

table_name

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

‘data_file’

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

BATCHSIZE=batch_size

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

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

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

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.NETQYH.BlukInsertTestsql.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(); 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 + "" + str1Result, strTestResult); //Console.Read(); /// summary  /// 批量插入测试 /// /summary  private static void BulkInsertTest() string strFilePath = @"D:学习ASP.NETQYH.BlukInsertTestsql.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.NETQYH.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多分钟

再加一点,我最近试了试,会出现字符转换的问题,可以把字段都该成为字符串的,这个主要是为了测试用,加入一条一条的插入1000万条最少也要20分钟左右吧,使用这个的话就比较迅速了,转换完成后一般保存的是这个类型看图,需要改为选中的那个!!如果有帮助可点个赞。