.net 使用SqlBulkCopy极速插入数据到 SQL Server

来源:互联网 发布:功能测试软件 编辑:程序博客网 时间:2024/05/17 06:09
 

刚进公司时,领导说物流水系统有一个问题:发送水票速度很慢,每发送一次就得等10多分钟,问我有没有解决方法,时间原因一直没去研究。

今天早上reader 上收到cnblogs的订阅里看到一个关于SQL语句快速插入的文章,提到SqlBulkCopy,感觉不错,按他的测试SqlBulkCopy要比普通插入快近30倍,

按这个来算,我们那个发水票的时间就会由 10分钟-->20秒,这可太神奇了。

于是乎,下demo,测试,改成自己一般使用的方法测试,NND,还真可以说是极速。

 在此贴上我的Demo:UploadFiles//SqlBulkCopy.rar

view plaincopy to clipboardprint?
  1. using System;   
  2. using System.Diagnostics;   
  3. using System.Data;   
  4. using System.Data.SqlClient;   
  5. using Microsoft.ApplicationBlocks.Data;   
  6. using System.Text;   
  7.   
  8. namespace ConsoleAppInsertTest   
  9. {   
  10.     class Program   
  11.     {   
  12.         static int count = 100000;           //插入的条数  
  13.         static void Main(string[] args)   
  14.         {   
  15.             long runTime = 0;   
  16.   
  17.             SqlHelper.ExecuteNonQuery(SqlHelper.SqlConnection, CommandType.Text, "TRUNCATE TABLE dbo.Passport");   
  18.             runTime = SqlBulkCopyInsert();   
  19.             Console.WriteLine(string.Format("使用SqlBulkCopy插入{1}条数据所用的时间是{0}毫秒", runTime, count));   
  20.   
  21.             SqlHelper.ExecuteNonQuery(SqlHelper.SqlConnection, CommandType.Text, "TRUNCATE TABLE dbo.Passport");   
  22.             runTime = TransactionInsert2();   
  23.             Console.WriteLine(string.Format("       使用事务插入{1}条数据所用的时间是{0}毫秒  --使用事务插入数据,分组执行", runTime, count));   
  24.   
  25.             SqlHelper.ExecuteNonQuery(SqlHelper.SqlConnection, CommandType.Text, "TRUNCATE TABLE dbo.Passport");   
  26.             runTime = TransactionInsert1();   
  27.             Console.WriteLine(string.Format("       使用事务插入{1}条数据所用的时间是{0}毫秒  --先存到string再一次性执行", runTime, count));   
  28.   
  29.             SqlHelper.ExecuteNonQuery(SqlHelper.SqlConnection, CommandType.Text, "TRUNCATE TABLE dbo.Passport");   
  30.             runTime = TransactionInsert();   
  31.             Console.WriteLine(string.Format("       使用事务插入{1}条数据所用的时间是{0}毫秒  --在事务里一条一条执行", runTime, count));   
  32.   
  33.   
  34.             SqlHelper.ExecuteNonQuery(SqlHelper.SqlConnection, CommandType.Text, "TRUNCATE TABLE dbo.Passport");   
  35.             runTime = CommonInsert1();   
  36.             Console.WriteLine(string.Format("       普通方式插入{1}条数据所用的时间是{0}毫秒 --保持SqlConnection", runTime, count));   
  37.   
  38.             SqlHelper.ExecuteNonQuery(SqlHelper.SqlConnection, CommandType.Text, "TRUNCATE TABLE dbo.Passport");   
  39.             runTime = CommonInsert();   
  40.             Console.WriteLine(string.Format("       普通方式插入{1}条数据所用的时间是{0}毫秒  --一条一条插入", runTime, count));   
  41.   
  42.             //使用SqlBulkCopy插入100000条数据所用的时间是1301毫秒  
  43.             //       使用事务插入100000条数据所用的时间是5811毫秒  --使用事务插入数据,分组执行  
  44.             //       使用事务插入100000条数据所用的时间是23315毫秒  --先存到string再一次性执行  
  45.             //       使用事务插入100000条数据所用的时间是15756毫秒  --在事务里一条一条执行  
  46.             //       普通方式插入100000条数据所用的时间是50287毫秒 --保持SqlConnection  
  47.             //       普通方式插入100000条数据所用的时间是49693毫秒  --一条一条插入  
  48.   
  49.             //使用SqlBulkCopy插入100000条数据所用的时间是1257毫秒  
  50.             //       使用事务插入100000条数据所用的时间是5870毫秒  --使用事务插入数据,分组执行  
  51.             //       使用事务插入100000条数据所用的时间是25062毫秒  --先存到string再一次性执行  
  52.             //       使用事务插入100000条数据所用的时间是16943毫秒  --在事务里一条一条执行  
  53.             //       普通方式插入100000条数据所用的时间是55764毫秒 --保持SqlConnection  
  54.             //       普通方式插入100000条数据所用的时间是58620毫秒  --一条一条插入  
  55.   
  56.             //使用SqlBulkCopy插入100000条数据所用的时间是1409毫秒  
  57.             //       使用事务插入100000条数据所用的时间是6041毫秒  --使用事务插入数据,分组执行  
  58.             //       使用事务插入100000条数据所用的时间是23330毫秒  --先存到string再一次性执行  
  59.             //       使用事务插入100000条数据所用的时间是15313毫秒  --在事务里一条一条执行  
  60.             //       普通方式插入100000条数据所用的时间是50665毫秒 --保持SqlConnection  
  61.             //       普通方式插入100000条数据所用的时间是50775毫秒  --一条一条插入  
  62.   
  63.             //通过三次测试分析发现,SqlBulkCopy速度是最快的,其次是SQL语句组合分组后执行,然后是SQL事务一条一条执行,然后是其它的  
  64.             //速度比是1:5:15:50,推荐前两种方法   
  65.   
  66.             Console.ReadLine();   
  67.   
  68.         }   
  69.   
  70.         /// <summary>   
  71.         /// 使用普通插入数据   
  72.         /// </summary>   
  73.         /// <returns></returns>  
  74.         private static long CommonInsert()   
  75.         {   
  76.             Stopwatch stopwatch = new Stopwatch();   
  77.             stopwatch.Start();   
  78.             for (int i = 0; i < count; i++)   
  79.             {   
  80.                 SqlHelper.ExecuteNonQuery(SqlHelper.SqlConnection, CommandType.Text, "insert into passport(PassportKey) values('" + Guid.NewGuid() + "')");   
  81.             }   
  82.             stopwatch.Stop();   
  83.             return stopwatch.ElapsedMilliseconds;   
  84.         }   
  85.   
  86.   
  87.         /// <summary>   
  88.         /// 使用普通插入数据,保持SqlConnection   
  89.         /// </summary>   
  90.         /// <returns></returns>   
  91.         private static long CommonInsert1()   
  92.         {   
  93.             Stopwatch stopwatch = new Stopwatch();   
  94.             stopwatch.Start();   
  95.             SqlConnection sqlconn = new SqlConnection(SqlHelper.SqlConnection);   
  96.             for (int i = 0; i < count; i++)   
  97.             {   
  98.                 SqlHelper.ExecuteNonQuery(sqlconn, CommandType.Text, "insert into passport(PassportKey) values('" + Guid.NewGuid() + "')");   
  99.             }   
  100.             stopwatch.Stop();   
  101.             return stopwatch.ElapsedMilliseconds;   
  102.         }   
  103.   
  104.   
  105.         /// <summary>   
  106.         /// 使用事务插入数据   
  107.         /// </summary>   
  108.         /// <returns></returns>   
  109.         private static long TransactionInsert()   
  110.         {   
  111.             Stopwatch stopwatch = new Stopwatch();   
  112.             stopwatch.Start();   
  113.   
  114.             using (SqlConnection ConnNow = new SqlConnection(SqlHelper.SqlConnection))   
  115.             {   
  116.                 ConnNow.Open();   
  117.                 using (SqlTransaction trans = ConnNow.BeginTransaction())   
  118.                 {   
  119.                     try  
  120.                     {   
  121.                         for (int i = 0; i < count; i++)   
  122.                         {   
  123.                             SqlHelper.ExecuteNonQuery(trans, CommandType.Text, "insert into passport(PassportKey) values('" + Guid.NewGuid() + "')");   
  124.                         }   
  125.                         trans.Commit();   
  126.                     }   
  127.                     catch (Exception ex)   
  128.                     {   
  129.                         trans.Rollback();   
  130.                     }   
  131.                 }   
  132.             }   
  133.   
  134.             stopwatch.Stop();   
  135.             return stopwatch.ElapsedMilliseconds;   
  136.         }   
  137.   
  138.         /// <summary>   
  139.         /// 使用事务插入数据,先存到string再一次性执行  
  140.         /// </summary>   
  141.         /// <returns></returns>  
  142.         private static long TransactionInsert1()   
  143.         {   
  144.             Stopwatch stopwatch = new Stopwatch();   
  145.             stopwatch.Start();   
  146.             StringBuilder sb = new StringBuilder();   
  147.             for (int i = 0; i < count; i++)   
  148.             {   
  149.                 sb.AppendFormat("insert into passport(PassportKey) values('{0}');", Guid.NewGuid());   
  150.             }   
  151.             using (SqlConnection ConnNow = new SqlConnection(SqlHelper.SqlConnection))   
  152.             {   
  153.                 ConnNow.Open();   
  154.                 using (SqlTransaction trans = ConnNow.BeginTransaction())   
  155.                 {   
  156.                     try  
  157.                     {   
  158.                         SqlHelper.ExecuteNonQuery(trans, CommandType.Text, sb.ToString());   
  159.                         for (int i = 0; i < count; i++)   
  160.                         {   
  161.                             SqlHelper.ExecuteNonQuery(trans, CommandType.Text, "insert into passport(PassportKey) values('" + Guid.NewGuid() + "')");   
  162.                         }   
  163.                         trans.Commit();   
  164.                     }   
  165.                     catch (Exception ex)   
  166.                     {   
  167.                         trans.Rollback();   
  168.                     }   
  169.                 }   
  170.             }   
  171.   
  172.             stopwatch.Stop();   
  173.             return stopwatch.ElapsedMilliseconds;   
  174.         }   
  175.   
  176.         /// <summary>   
  177.         /// 使用事务插入数据,分组执行-- 感谢 闫道民 提供  
  178.         /// </summary>   
  179.         /// <returns></returns>  
  180.         private static long TransactionInsert2()   
  181.         {   
  182.             Stopwatch stopwatch = new Stopwatch();   
  183.             stopwatch.Start();   
  184.             using (SqlConnection ConnNow = new SqlConnection(SqlHelper.SqlConnection))   
  185.             {   
  186.                 ConnNow.Open();   
  187.                 string tmp = string.Empty; ;   
  188.                 int itmp = 0;   
  189.                 using (SqlTransaction trans = ConnNow.BeginTransaction())   
  190.                 {   
  191.                     try  
  192.                     {   
  193.                         for (int i = 0; i < count; i++)   
  194.                         {   
  195.                             itmp++;   
  196.                             tmp = tmp + "insert into passport(PassportKey) values('" + Guid.NewGuid() + "');";   
  197.                             if (itmp == 180)   
  198.                             {   
  199.                                 itmp = 0;   
  200.                                 SqlHelper.ExecuteNonQuery(trans, CommandType.Text, tmp);   
  201.                                 tmp = string.Empty;   
  202.                             }   
  203.                         }   
  204.                         SqlHelper.ExecuteNonQuery(trans, CommandType.Text, tmp);   
  205.                         trans.Commit();   
  206.                     }   
  207.                     catch (Exception ex)   
  208.                     {   
  209.                         trans.Rollback();   
  210.                     }   
  211.                 }   
  212.             }   
  213.   
  214.             stopwatch.Stop();   
  215.             return stopwatch.ElapsedMilliseconds;   
  216.         }   
  217.   
  218.         /// <summary>   
  219.         /// 使用SqlBulkCopy方式插入数据  
  220.         /// </summary>   
  221.         /// <returns></returns>  
  222.         private static long SqlBulkCopyInsert()   
  223.         {   
  224.             Stopwatch stopwatch = new Stopwatch();   
  225.             stopwatch.Start();   
  226.   
  227.             DataTable dataTable = GetTableSchema();   
  228.             for (int i = 0; i < count; i++)   
  229.             {   
  230.                 DataRow dataRow = dataTable.NewRow();   
  231.                 dataRow[2] = Guid.NewGuid();   
  232.                 dataTable.Rows.Add(dataRow);   
  233.             }   
  234.   
  235.             //Console.WriteLine(stopwatch.ElapsedMilliseconds);//初始化数据时间  
  236.   
  237.             SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(SqlHelper.SqlConnection);   
  238.             sqlBulkCopy.DestinationTableName = "Passport";   
  239.   
  240.             if (dataTable != null && dataTable.Rows.Count != 0)   
  241.             {   
  242.                 sqlBulkCopy.WriteToServer(dataTable);   
  243.             }   
  244.             sqlBulkCopy.Close();   
  245.   
  246.   
  247.             stopwatch.Stop();   
  248.             return stopwatch.ElapsedMilliseconds;   
  249.         }   
  250.   
  251.   
  252.         private static DataTable GetTableSchema()   
  253.         {   
  254.             return SqlHelper.ExecuteDataset(SqlHelper.SqlConnection, CommandType.Text, "select * from Passport where 1=2").Tables[0];   
  255.         }   
  256.   
  257.     }   
  258. }  
原创粉丝点击