此文原创自CSDN TJVictor专栏:http://blog.csdn.net/tjvictor/archive/2009/07/18/4360030.aspx

在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致SQL一系统性能问题。下面介绍SQL Server支持的两种批量数据插入方法:Bulk和表值参数(Table-Valued Parameters)。

运行下面的脚本,建立测试数据库和表值参数。

  1. --Create DataBase
  2. create database BulkTestDB;
  3. go
  4. use BulkTestDB;
  5. go
  6. --Create Table
  7. Create table BulkTestTable(
  8. Id int primary key,
  9. UserName nvarchar(32),
  10. Pwd varchar(16))
  11. go
  12. --Create Table Valued
  13. CREATE TYPE BulkUdt AS TABLE
  14. (Id int,
  15. UserName nvarchar(32),
  16. Pwd varchar(16))

下面我们使用最简单的Insert语句来插入100万条数据,代码如下:

  1. Stopwatch sw = new Stopwatch();
  2. SqlConnection sqlConn = new SqlConnection(
  3. ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString);//连接数据库
  4. SqlCommand sqlComm = new SqlCommand();
  5. sqlComm.CommandText = string.Format("insert into BulkTestTable(Id,UserName,Pwd)values(@p0,@p1,@p2)");//参数化SQL
  6. sqlComm.Parameters.Add("@p0", SqlDbType.Int);
  7. sqlComm.Parameters.Add("@p1", SqlDbType.NVarChar);
  8. sqlComm.Parameters.Add("@p2", SqlDbType.VarChar);
  9. sqlComm.CommandType = CommandType.Text;
  10. sqlComm.Connection = sqlConn;
  11. sqlConn.Open();
  12. try
  13. {
  14. //循环插入100万条数据,每次插入10万条,插入10次。
  15. for (int multiply = 0; multiply < 10; multiply++)
  16. {
  17. for (int count = multiply * 100000; count < (multiply + 1) * 100000; count++)
  18. {
  19. sqlComm.Parameters["@p0"].Value = count;
  20. sqlComm.Parameters["@p1"].Value = string.Format("User-{0}", count * multiply);
  21. sqlComm.Parameters["@p2"].Value = string.Format("Pwd-{0}", count * multiply);
  22. sw.Start();
  23. sqlComm.ExecuteNonQuery();
  24. sw.Stop();
  25. }
  26. //每插入10万条数据后,显示此次插入所用时间
  27. Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));
  28. }
  29. }
  30. catch (Exception ex)
  31. {
  32. throw ex;
  33. }
  34. finally
  35. {
  36. sqlConn.Close();
  37. }
  38. Console.ReadLine();

耗时图如下:

由于运行过慢,才插入10万条就耗时72390 milliseconds,所以我就手动强行停止了。

下面看一下使用Bulk插入的情况:

bulk方法主要思想是通过在客户端把数据都缓存在Table中,然后利用SqlBulkCopy一次性把Table中的数据插入到数据库

代码如下:

  1. public static void BulkToDB(DataTable dt)
  2. {
  3. SqlConnection sqlConn = new SqlConnection(
  4. ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString);
  5. SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlConn);
  6. bulkCopy.DestinationTableName = "BulkTestTable";
  7. bulkCopy.BatchSize = dt.Rows.Count;
  8. try
  9. {
  10. sqlConn.Open();
  11. if (dt != null && dt.Rows.Count != 0)
  12. bulkCopy.WriteToServer(dt);
  13. }
  14. catch (Exception ex)
  15. {
  16. throw ex;
  17. }
  18. finally
  19. {
  20. sqlConn.Close();
  21. if (bulkCopy != null)
  22. bulkCopy.Close();
  23. }
  24. }
  25. public static DataTable GetTableSchema()
  26. {
  27. DataTable dt = new DataTable();
  28. dt.Columns.AddRange(new DataColumn[]{
  29. new DataColumn("Id",typeof(int)),
  30. new DataColumn("UserName",typeof(string)),
  31. new DataColumn("Pwd",typeof(string))});
  32. return dt;
  33. }
  34. static void Main(string[] args)
  35. {
  36. Stopwatch sw = new Stopwatch();
  37. for (int multiply = 0; multiply < 10; multiply++)
  38. {
  39. DataTable dt = Bulk.GetTableSchema();
  40. for (int count = multiply * 100000; count < (multiply + 1) * 100000; count++)
  41. {
  42. DataRow r = dt.NewRow();
  43. r[0] = count;
  44. r[1] = string.Format("User-{0}", count * multiply);
  45. r[2] = string.Format("Pwd-{0}", count * multiply);
  46. dt.Rows.Add(r);
  47. }
  48. sw.Start();
  49. Bulk.BulkToDB(dt);
  50. sw.Stop();
  51. Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));
  52. }
  53. Console.ReadLine();
  54. }

耗时图如下:

可见,使用Bulk后,效率和性能明显上升。使用Insert插入10万数据耗时72390,而现在使用Bulk插入100万数据才耗时17583。

最后再看看使用表值参数的效率,会另你大为惊讶的。

表值参数是SQL Server 2008新特性,简称TVPs。对于表值参数不熟悉的朋友,可以参考最新的book online,我也会另外写一篇关于表值参数的博客,不过此次不对表值参数的概念做过多的介绍。言归正传,看代码:

  1. public static void TableValuedToDB(DataTable dt)
  2. {
  3. SqlConnection sqlConn = new SqlConnection(
  4. ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString);
  5. const string TSqlStatement =
  6. "insert into BulkTestTable (Id,UserName,Pwd)" +
  7. " SELECT nc.Id, nc.UserName,nc.Pwd" +
  8. " FROM @NewBulkTestTvp AS nc";
  9. SqlCommand cmd = new SqlCommand(TSqlStatement, sqlConn);
  10. SqlParameter catParam = cmd.Parameters.AddWithValue("@NewBulkTestTvp", dt);
  11. catParam.SqlDbType = SqlDbType.Structured;
  12. //表值参数的名字叫BulkUdt,在上面的建立测试环境的SQL中有。
  13. catParam.TypeName = "dbo.BulkUdt";
  14. try
  15. {
  16. sqlConn.Open();
  17. if (dt != null && dt.Rows.Count != 0)
  18. {
  19. cmd.ExecuteNonQuery();
  20. }
  21. }
  22. catch (Exception ex)
  23. {
  24. throw ex;
  25. }
  26. finally
  27. {
  28. sqlConn.Close();
  29. }
  30. }
  31. public static DataTable GetTableSchema()
  32. {
  33. DataTable dt = new DataTable();
  34. dt.Columns.AddRange(new DataColumn[]{
  35. new DataColumn("Id",typeof(int)),
  36. new DataColumn("UserName",typeof(string)),
  37. new DataColumn("Pwd",typeof(string))});
  38. return dt;
  39. }
  40. static void Main(string[] args)
  41. {
  42. Stopwatch sw = new Stopwatch();
  43. for (int multiply = 0; multiply < 10; multiply++)
  44. {
  45. DataTable dt = TableValued.GetTableSchema();
  46. for (int count = multiply * 100000; count < (multiply + 1) * 100000; count++)
  47. {
  48. DataRow r = dt.NewRow();
  49. r[0] = count;
  50. r[1] = string.Format("User-{0}", count * multiply);
  51. r[2] = string.Format("Pwd-{0}", count * multiply);
  52. dt.Rows.Add(r);
  53. }
  54. sw.Start();
  55. TableValued.TableValuedToDB(dt);
  56. sw.Stop();
  57. Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));
  58. }
  59. Console.ReadLine();
  60. }

耗时图如下:

比Bulk还快5秒。

SQL Server 批量插入数据的两种方法(转)的更多相关文章

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

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

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

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

  3. SQLServer 批量插入数据的两种方法

    SQLServer 批量插入数据的两种方法-发布:dxy 字体:[增加 减小] 类型:转载 在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Ins ...

  4. SQL 2005批量插入数据的二种方法

    SQL 2005批量插入数据的二种方法 Posted on 2010-07-22 18:13 moss_tan_jun 阅读(2635) 评论(2) 编辑 收藏 在SQL Server 中插入一条数据 ...

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

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

  6. MyBatis 批量插入数据的 3 种方法!

    批量插入功能是我们日常工作中比较常见的业务功能之一,之前我也写过一篇关于<MyBatis Plus 批量数据插入功能,yyds!>的文章,但评论区的反馈不是很好,主要有两个问题:第一,对 ...

  7. MySQL批量插入数据的几种方法

    最近公司要求测试数据库的性能,就上网查了一些批量插入数据的代码,发现有好几种不同的用法,插入同样数据的耗时也有区别 别的先不说,先上一段代码与君共享 方法一: package com.bigdata; ...

  8. SQL Server中迁移数据的几种方法

    1.通过工具"DTS"的设计器进行导入或者导出 DTS的设计器功能强大,支持多任务,也是可视化界面,容易操作,但知道的人一般不 多,如果只是进行SQL Server数据库中部分表的 ...

  9. SQL Server 批量插入数据的方法

    运行下面的脚本,建立测试数据库和表. --Create DataBase create database BulkTestDB; go use BulkTestDB; go --Create Tabl ...

随机推荐

  1. js仿手机端九宫格登录功能

    js仿手机端九宫格登录功能 最近闲来无事把以前无聊时开发的小东西拿出来和大家分享下,写的不好的请指出,我会及时修改.谢谢. 功能及方法逻辑都注释在代码中.所以麻烦大家直接看代码. 效果如下: 话不多说 ...

  2. delphi TeeChart保存3种图片文件

    var vForm: Tfrm_ChemaShowMainChild;begin vForm := GetActiveForm; vForm.cht_Edit.SaveToMetafile('C:\1 ...

  3. HDU5808Price List Strike Back (BestCoder Round #86 E) cdq分治+背包

    严格按题解写,看能不能形成sum,只需要分割当前sum怎么由两边组成就好 #include <cstdio> #include <cstring> #include <c ...

  4. php获取网站根目录

    php获取网站根目录方法一:<?phpdefine("WWWROOT",str_ireplace(str_replace("/","\\&quo ...

  5. kali linux 一些工具及命令集1(搜集DNS信息)

    DNS信息收集 1.dnsdict6   用于查看ipv6的dns信息,国内很少ipv6,基本无用 2.dnsmap 收集dns信息,同类别还有dnsenum,dnswalk 使用dnsmap需先找到 ...

  6. win7 共享的问题,"您可能没有权限使用网络资源"的解决办法

    重点来了,如果以上方法都不行的话,下面这个绝对有效,本人屡试不爽.1 打开受访者的guest权限2 开始--运行--gpedit.msc3 windows设置---安全设置--本地策略--用户权利指派 ...

  7. 传统企业,"哀兵必胜"的想法要不得

    [文/ 任英杰]同事在内网上发了一篇文章『哀兵必胜』,思量数日,作文应对.文中表达的积极精神让人敬佩,但背后似乎隐含着一股莫名的“情绪”.对行业大格局的基本看法会影响公司转型的成败,觉得还是有必要讨论 ...

  8. 原型模式--prototype

    C++设计模式——原型模式 什么是原型模式? 在GOF的<设计模式:可复用面向对象软件的基础>中是这样说的:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.这这个定义中,最 ...

  9. Android中的颜色值RGB对照表表

    Android中颜色值是通过红(Red).绿(Green).蓝 (Blue)三原色,以及一个透明度(Alpha)值来表示的,颜色值总是以井号(#)开头,接下来就是Alpha-Red-Green-Blu ...

  10. cocos2d-html5将js编译为jsc

    在d:\DevTool\cocos2d-x-2.2.2\cocos2d-x-2.2.2\tools\cocos2d-console\console 有 cocos2d_jscompile.py coc ...