SqlBulkCopy加了事務真的會變快嗎?


在上一篇文章不同版本的SQL Server之間數據導出導入的方法及性能比較中比較了5種方法進行數據遷移的效率,最后發現使用SqlBulkCopy具有極高的性能。

在文章的回復中,園友溫景良(Jason)提到:sqlbulkcopy如果加上事務呢,速度應該快些吧!

當時我一想,SqlBulkCopy可以包含在事務里面執行嗎?因為我記得SqlBulkCopy是基於BCP且不寫log的。所以也沒敢倉促回復。

然后我去查了下,的確是可以包含在事務中執行的,且提供了兩種方法。

使用UseInternalTransaction

在構造函數SqlBulkCopy(String, SqlBulkCopyOptions)里面有SqlBulkCopyOptions的選項,有如下可選項。

我們看到可選項分別有保持Identity鍵,檢查約束,是否鎖表,保持null值,觸發觸發器,使用事務。

所以如果只是想把SqlBulkCopy包含在事務中,只要打開此屬性即可。

使用System.Data.SqlClient.SqlTransaction

使用自定義的事務,將SqlBulkCopy和其他操作一起包含在一個事務中。

這種方法只要使用另一個構造函數即可:SqlBulkCopy(SqlConnection, SqlBulkCopyOptions, SqlTransaction)。

需要注意的是:當打開了UseInternalTransaction選項后,就不可以和自定義事務一起使用了,否則會拋出InvalidArgumentException。

事務影響性能?

下面是使用第一種開啟事務的測試代碼,沒有使用事務的代碼參見前一篇文章

使用UseInternalTransaction的代碼。

 1  using System;
 2  using System.Data;
 3  using System.Data.SqlClient;
 4 
 5  namespace BulkInsert
 6 {
 7      static  class Program
 8     {
 9          static  void Main()
10         {
11             DateTime dateTimeStart = DateTime.Now;
12             Console.WriteLine( " Start Insert: " + dateTimeStart.ToString( " HH:mm:ss fff "));
13              // 導入導出的數據庫連接
14               // SqlConnection connectionDestination = new SqlConnection();
15              SqlConnection connectionSource =  new SqlConnection( " Server =.; User ID=sa; Password=password; Initial CataLog=ExportDataDemo_Source; ");
16 
17              // 實例化一個SqlBulkCopy
18               var bulker =  new SqlBulkCopy( " Server =.; User ID=sa; Password=password; Initial CataLog=ExportDataDemo_Destination; ", SqlBulkCopyOptions.UseInternalTransaction) { DestinationTableName =  " DEMOTABLE ", BulkCopyTimeout =  600 };
19 
20              // 獲取源數據庫的數據
21              SqlCommand sqlcmd =  new SqlCommand( " SELECT * FROM DEMOTABLE ", connectionSource);
22             SqlDataAdapter sqlDataAdapter =  new SqlDataAdapter(sqlcmd);
23             DataTable dataTableSource =  new DataTable();
24             sqlDataAdapter.Fill(dataTableSource);
25 
26              // 可以重新定義字段的Mapping關系
27               // SqlBulkCopyColumnMapping sqlBulkCopyColumnMapping = new SqlBulkCopyColumnMapping("COL1", "NEW_COL1");
28               // bulker.ColumnMappings.Add(sqlBulkCopyColumnMapping);
29               // connectionDestination.Open();
30              bulker.WriteToServer(dataTableSource);
31             bulker.Close();
32             DateTime dateTimeEnd = DateTime.Now;
33             Console.WriteLine( " Insert Ending: " + dateTimeEnd.ToString( " HH:mm:ss fff "));
34         }
35     }
36 } 

Source表同樣還是10萬的數據,每遷移一次后使用TRUNCATE TABLE清空數據,測試三次取平均值。

截圖如下。

A:不使用事務

B:使用事務

最終對比數據。單位為秒,忘記加在圖表上面了 :)

特定的測試環境與數據,測試結果僅供參考,歡迎交流、討論。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM