好多天沒寫博客了,剛剛畢業一個多月!
關於上一篇博客中提到的,在進行批量數據插入數據庫的時候可以通過給存儲過程傳遞一個類型為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語句更高效。
本人才疏學淺,哪里有不對的歡迎指出。