2012-10-23 53 views
2

我有一些代碼,在程序生命的最後,將6個不同列表的全部內容上傳到數據庫中。問題是,它們是平行的列表,每個列表中大約有14,000個項目,我必須針對每個單獨的項目運行Insert查詢。這需要很長時間,有沒有更快的方法來做到這一點?下面是相關的代碼示例:更快上傳到數據庫

public void uploadContent() 
    { 
     var cs = Properties.Settings.Default.Database; 
     SqlConnection dataConnection = new SqlConnection(cs); 
     dataConnection.Open(); 

     for (int i = 0; i < urlList.Count; i++) 
     { 
      SqlCommand dataCommand = new SqlCommand(Properties.Settings.Default.CommandString, dataConnection); 
      try 
      { 
       dataCommand.Parameters.AddWithValue("@user", userList[i]); 
       dataCommand.Parameters.AddWithValue("@computer", computerList[i]); 
       dataCommand.Parameters.AddWithValue("@date", timestampList[i]); 
       dataCommand.Parameters.AddWithValue("@itemName", domainList[i]); 
       dataCommand.Parameters.AddWithValue("@itemDetails", urlList[i]); 
       dataCommand.Parameters.AddWithValue("@timesUsed", hitsList[i]); 

       dataCommand.ExecuteNonQuery(); 
      } 
      catch (Exception e) 
      { 
       using (StreamWriter sw = File.AppendText("errorLog.log")) 
       { 
        sw.WriteLine(e); 
       } 
      } 

     } 
     dataConnection.Close(); 
    } 

這裏是命令串代碼是從配置文件中拉:外

INSERT dbo.InternetUsage VALUES (@user, @computer, @date, @itemName, @itemDetails, @timesUsed) 
+0

我之前已經生成了XML,上傳到了一個獲取XML並使用服務器端XML查詢將存儲節點處理成錶行的sproc。意味着它只是一個調用,並且服務器執行所有數千行的處理。 – Lloyd

+3

你正在使用哪個數據庫,通常你會想要在一個命令中運行多個插入。例如,請看這篇文章:http://stackoverflow.com/questions/2624713/how-do-i-insert-multiple-rows-without-repeating-the-insert-into-dbo-blah-part – Simon

+0

@Simon我會給那一槍。我沒有考慮這樣做。謝謝。 –

回答

2

正如@ alerya的答覆中提到,執行以下操作將有助於(這裏補充說明)

1)make命令和參數創建以外的for循環 由於相同的命令時,每次配合使用,每次重新創建命令都沒有意義。除了創建一個新對象(需要花費時間)之外,該命令還必須在每次爲幾件事創建(表存在等)時進行驗證。這會帶來很多開銷。

2)將插入一個交易 把所有插入的事務中會加快速度,因爲在默認情況下,這不是一個事務中的命令將被視爲其自己的事務中。因此,每次插入內容時,數據庫服務器都必須驗證它剛纔插入的內容是否實際保存了(通常在硬盤上,這受到磁盤速度的限制)。但是,如果多個INSERT在一個事務中,則只需執行一次該檢查。

基於你已經顯示的代碼,這種方法的缺點是一個錯誤的INSERT會破壞一堆。這是否可以接受取決於您的具體要求。

Aside 你真的應該做的另一件事(雖然這不會在短期內加快速度)正確使用IDisposable接口。這意味着無論是在所有IDisposable的對象(的SqlConnection,SqlCommand的)調用.Dispose(),或理想地,在使用包裹它們()塊:

using(SqlConnection dataConnection = new SqlConnection(cs) 
{ 
    //Code goes here 
} 

這將防止這些斑點內存泄漏,這將成爲一個問題很快,如果你的循環太大。

+0

謝謝。我在循環之外創建了命令,然後我使用了Bulk Insert,因此它全部在一個事務中。現在我只是在等待我們的數據庫管理員給我批量加載數據庫的權限。 –

+0

@RyanDuffing,這很好。只要確保使用'using()'構造,或者至少在每個'IDisposable'對象上調用'.dispose()'! – sybkar

2
  1. make命令和參數的創建:

    的CommandString for(int i = 0; i < urlList.Count; i ++)

  2. 也在事務中創建插入
  3. 如果可能創建一個存儲過程並將參數傳遞爲DataTable。
+2

3)僅適用於SQL Server> 2005。 –

-1

爲什麼不從一個單獨的線程運行您的uploadContent()方法。
這樣你就不用擔心查詢執行的時間。

+1

他關注插入的時間。他並沒有說它阻止了他做別的事情......他還指出它已經在一個程序的末尾,所以在另一個線程上做這件事對於防止其他事情的發生並沒有什麼影響。 – sybkar

1

由於數據庫服務器的往返行爲,將INSERT命令逐個發送到數據庫將確實使整個過程變得緩慢。如果您擔心性能問題,則應考慮使用批量插入策略。您可以:

  1. 以BULK INSERT理解的格式生成包含所有信息的平面文件。
  2. 使用BULK INSERT命令將該文件導入數據庫(http://msdn.microsoft.com/en-us/library/ms188365(v=sql.90).aspx)。

Ps。我想當你說你正在使用MS SQL Server的SQL。