转自:https://www.cnblogs.com/LenLi/p/3903641.html
结合博主实例,自己测试了一下,把数据改为3万行更明显!!
关于上一篇博客中提到的,在进行批量数据插入数据库的时候可以通过给存储过程传递一个类型为Table的参数进行相关操作,在这个过程中本人没有进行效率的测试。后来查找发现可以通过SqlBulkCopy类进行大数据插入操作,本文就来介绍一个这个类的作用并做了相关的效率测试(与Insert语句进行对比)。
SqlBulkCopy只能向SqlServer表写入数据,该表既可以是同一个服务器上的也可以是远程服务器上的。当然要写入的数据即数据源不单单是SqlServer,可以是任何数据源,只要数据可以加载到DataTable中或者DataReader可以读取的数据。
SqlBulkCopy类批量插入数据代码如下:
1.先创建一个User类,对应数据库的User表。
1 public class User 2 { 3 public User() 4 { 5 6 } 7 public string UserName { get; set; } 8 public string PassWord { get; set; } 9 public string Address { get; set; } 10 public string Telephone { get; set; } 11 }
数据库User表结构:
2.创建一个返回存储了一万条数据的DataTable方法:
1 protected DataTable GetDataTableData() 2 { 3 List<User> userList=new List<User>(); 4 for (int i = 0; i < 10000; i++) 5 { 6 User user=new User(); 7 user.UserName = "zhangsan"; 8 user.PassWord = "123456"; 9 user.Address = "北京路一号"; 10 user.Telephone = "13232323232"; 11 userList.Add(user); 12 } 13 using (DataTable dt = new DataTable()) 14 { 15 dt.Columns.Add("UserName", typeof (string)); 16 dt.Columns.Add("PassWord", typeof(string)); 17 dt.Columns.Add("Address", typeof(string)); 18 dt.Columns.Add("Telephone", typeof(string)); 19 foreach (User user in userList) 20 { 21 DataRow dr = dt.NewRow(); 22 dr["UserName"] = user.UserName; 23 dr["PassWord"] = user.PassWord; 24 dr["Address"] = user.Address; 25 dr["Telephone"] = user.Telephone; 26 dt.Rows.Add(dr); 27 } 28 return dt; 29 } 30 }
3.在页面上放了一个按钮,点击该按钮便可进行数据的插入操作,按钮点击事件代码如下:
1 protected void Button1_Click(object sender, EventArgs e) 2 { 3 string conStr = ConfigurationManager.ConnectionStrings["conStr"].ConnectionString; 4 SqlConnection connection=new SqlConnection(conStr); 5 try 6 { 7 using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conStr, SqlBulkCopyOptions.KeepIdentity|SqlBulkCopyOptions.UseInternalTransaction)) 8 { 9 bulkCopy.DestinationTableName = "dbo.[User]";//目标表,就是说您将要将数据插入到哪个表中去 10 bulkCopy.ColumnMappings.Add("UserName", "UserName");//数据源中的列名与目标表的属性的映射关系 11 bulkCopy.ColumnMappings.Add("PassWord", "PassWord"); 12 bulkCopy.ColumnMappings.Add("Address", "Address"); 13 bulkCopy.ColumnMappings.Add("Telephone", "Telephone"); 14 DataTable dt = GetDataTableData();//数据源数据 15 //bulkCopy.BatchSize = 3; 16 Stopwatch stopwatch=new Stopwatch();//跑表,该类可以进行时间的统计 17 stopwatch.Start();//跑表开始 18 bulkCopy.WriteToServer(dt);//将数据源数据写入到目标表中 19 Response.Write("插入数据所用时间:"+stopwatch.Elapsed);//跑表结束,Elapsed是统计到的时间 20 } 21 } 22 catch (Exception ex) 23 { 24 throw new Exception(ex.Message); 25 } 26 Response.Write("<br/>插入成功!!!"); 27 }
SqlServer中通过Insert语句批量插入数据的代码如下:
1.首先创建一个插入一万条数据的存储过程,插入的数据与SqlBulkCopy插入的数据一模一样。
1 CREATE PROC USP_InsertUserTable 2 AS 3 BEGIN 4 DECLARE @i INT 5 SET @i=1 6 WHILE @i<10001 7 BEGIN 8 INSERT INTO dbo.[User] 9 ( UserName , 10 PassWord , 11 Address , 12 Telephone 13 ) 14 VALUES ( N'zhangsan' , -- UserName - nvarchar(50) 15 N'123456' , -- PassWord - nvarchar(6) 16 N'北京路一号' , -- Address - nvarchar(50) 17 '13232323232' -- Telephone - varchar(11) 18 ) 19 20 SET @i=@i+1 21 END 22 END
2.执行存储过程。
EXEC dbo.USP_InsertUserTable
SqlBulkCopy与Insert语句效率测试对比如下:
SqlBulkCopy所用时间统计(5次):
SqlServer Insert语句所用时间统计(5次),通过工具--》Sql Server Profiler进行测试,使用的模板是TSQL_Duration:
有一点需要注意的:无论是SqlBulkCopy还是Insert语句进行操作,每次测试前都应该进行缓冲区清理以及删除原有数据,以免对测试进行影响,代码如下:
DBCC DROPCLEANBUFFERS
DBCC FREESYSTEMCACHE( 'ALL' )
DELETE dbo.[User]
结论:通过以上的统计分析测试,可以看出SqlBulkCopy操作大数据插入的效率性能明显比Insert语句更高效。
注:SqlBulkCopy适用于单表的批量数据(几百行,上千行)操作,DbSession适用于单表或多表的少量数据操作。