2013-02-26 62 views
0

我正在做一個循環插入,如下所示(方法A),似乎每個循環調用數據庫不是一個好主意。我發現一種替代方法是在我的SProc中循環逗號分隔的字符串,而不是執行插入操作,以便只有一個條目進入數據庫。在性能方面會有什麼重大改進? :SQL Server +循環插入性能

方法A:

foreach (DataRow row in dt.Rows) 
{ 
    userBll = new UserBLL(); 
    UserId = (Guid)row["UserId"]; 
    // Call userBll method to insert into SQL Server with UserId as one of the parameter. 
} 

方法B:

string UserIds = "Tom, Jerry, 007"; // Assuming we already concatenate the strings. So no loops this time here. 
userBll = new UserBLL(); 
// Call userBll method to insert into SQL Server with 'UserIds' as parameter. 

方法B SPROC /執行在SPROC環插入件。

if right(rtrim(@UserIds), 1) <> ',' 
    SELECT @string = @UserIds + ',' 

SELECT @pos = patindex('%,%' , @UserIds) 

while @pos <> 0 
begin 
    SELECT @piece = left(@v, (@pos-1)) 

    -- Perform the insert here 

    SELECT @UserIds = stuff(@string, 1, @pos, '') 
    SELECT @pos = patindex('%,%' , @UserIds) 
end 
+0

我假設SQL Server - 如果是這樣,哪個版本? – Bridge 2013-02-26 15:00:16

+0

這是SQL Server 2008R2 – k80sg 2013-02-26 15:00:44

+0

您也可以通過'方法B + XML'將CSV值作爲行返回,而不循環,然後執行INSERT INTO TABLE SELECT * FROM ... – 2013-02-26 15:13:57

回答

1

較少的查詢通常意味着更快的處理。也就是說,我的一名同事在.NET框架的TSQL BULK INSERT的包裝上取得了一些成功,該框架由框架提供爲SqlBulkCopyThis MSDN blog entry shows how to use it

主要「API」的樣品是這樣(按原樣,將其寫入DataTable添加到SQL的內容從鏈接的文章取):

private void WriteToDatabase() 
{ 
    // get your connection string 
    string connString = ""; 
    // connect to SQL 
    using (SqlConnection connection = 
      new SqlConnection(connString)) 
    { 
     // make sure to enable triggers 
     // more on triggers in next post 
     SqlBulkCopy bulkCopy = 
      new SqlBulkCopy 
      (
      connection, 
      SqlBulkCopyOptions.TableLock | 
      SqlBulkCopyOptions.FireTriggers | 
      SqlBulkCopyOptions.UseInternalTransaction, 
      null 
      ); 

     // set the destination table name 
     bulkCopy.DestinationTableName = this.tableName; 
     connection.Open(); 

     // write the data in the "dataTable" 
     bulkCopy.WriteToServer(dataTable); 
     connection.Close(); 
    } 
    // reset 
    this.dataTable.Clear(); 
    this.recordCount = 0; 
} 

鏈接的文章解釋了需要做什麼利用這種機制。

0

如果您正在尋找與給定類型的多個輸入值更好的插入性能,我建議你看一下table valued parameters

和樣品,可以發現here,顯示出使用它們的一些示例代碼。

1

根據我的經驗,也有你不希望有每個記錄做三件事情:

  1. 打開/關閉每一個SQL連接行。這個問題由ADO.NET連接池處理。除非您禁用了池,否則您不必擔心它。

  2. 數據庫每行往返。這往往不太關於網絡帶寬或網絡延遲,更多的是關於客戶端線程休眠。每次喚醒時您都需要在客戶端進行大量的工作,或者您正在浪費時間片。

  3. 打開/關閉每行的sql事務日誌。打開和關閉日誌並不是免費的,但你也不想太長時間地打開它。在單個事務中執行多次插入,但不是太多。

對於其中的任何一種,您可能會看到很多改進,從每個請求1行到每個請求10行。您可以通過在傳輸批次之前在客戶端建立10條插入語句來實現此目的。

您將一個列表發送到proc的方法已經被Sommarskog寫入極端深度。