设为首页 收藏本站
查看: 1361|回复: 0

[经验分享] Sql Server海量数据插入

[复制链接]

尚未签到

发表于 2017-7-13 13:02:19 | 显示全部楼层 |阅读模式
  目录
  1.前言
  2.BULK INSERT
  3.简单示例
  前言
  由于昨天接到一个客户反馈导出数据卡死的问题,于是决定今天模拟一下千万级的数据,然后傻傻的等待插入数据了半天......
  对于海量数据,上百万上千万的数据插入,我们用ADO.NET提供的普通一条一条数据插入非常非常慢,好在Sql Server为我们提供了批量插入方法。
  BULK INSERT
  语法
DSC0000.png

  主要参数说明
  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三个简单的字段。
DSC0001.png

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


DSC0002.gif DSC0003.gif


/// <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++;
}
}
View Code  第三步:封装出两个方法,分别用来执行批量插入和普通插入,具体代码如下:





/// <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++;
}
}
View Code  第四步: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++;
}
}
}
}
View Code  示例中还用到两个辅助类,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();
}
}
}
View Code  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);
}
}
}
}
View Code  一切准备就绪,开始运行,结果如下:
DSC0004.png

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

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-393429-1-1.html 上篇帖子: SQL Server--用户自定义函数 下篇帖子: SQL Server-聚焦查询计划Stream Aggregate VS Hash Match Aggregate(二十)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表