2012-10-10 75 views
4

我們在C#中使用SqlBulk Copy類。在sql中插入批量數據。我們有一張有1000萬條記錄的表格。Sql批量複製內存問題

我們是在一個循環中插入一個批次的10,000個數據

我們正面臨的物理內存issue.The內存得到提高,沒有得到減少。

以下是我們的代碼。如何在使用sql批量複製時釋放內存,或者有任何其他方式進行批量插入。

using (System.Data.SqlClient.SqlBulkCopy bulkCopy = new System.Data.SqlClient.SqlBulkCopy(SQlConn,SqlBulkCopyOptions.TableLock,null)) 
{ 
    //bulkCopy = new System.Data.SqlClient.SqlBulkCopy(SQlConn); 
    bulkCopy.DestinationTableName = DestinationTable; 
    bulkCopy.BulkCopyTimeout = 0; 
    bulkCopy.BatchSize = dt1.Rows.Count; 
    Logger.Log("DATATABLE FINAL :" + dt1.Rows.Count.ToString(), Logger.LogType.Info); 
    if (SQlConn.State == ConnectionState.Closed || SQlConn.State == ConnectionState.Broken) 
     SQlConn.Open(); 
    bulkCopy.WriteToServer(dt1); //DataTable 
    SQlConn.Close(); 
    SQlConn.Dispose(); 
    bulkCopy.Close(); 
    if (bulkCopy != null) 
    { 
     ((IDisposable)bulkCopy).Dispose(); 
    }       
} 

這裏更新完整的代碼。

try 
     { 

      using (SqlConnection SQlConn = new SqlConnection(Common.SQLConnectionString)) 
      { 


       DataTable dt1 = FillEmptyDateFields(dtDestination); 

       //SqlTableCreator ObjTbl = new SqlTableCreator(SQlConn); 

       //ObjTbl.DestinationTableName = DestinationTable; 
       using (System.Data.SqlClient.SqlBulkCopy bulkCopy = new System.Data.SqlClient.SqlBulkCopy(SQlConn,SqlBulkCopyOptions.TableLock,null)) 
       { 

        //bulkCopy = new System.Data.SqlClient.SqlBulkCopy(SQlConn); 
        bulkCopy.DestinationTableName = DestinationTable; 
        bulkCopy.BulkCopyTimeout = 0; 
        bulkCopy.BatchSize = dt1.Rows.Count; 
        Logger.Log("DATATABLE FINAL :" + dt1.Rows.Count.ToString(), Logger.LogType.Info); 
        if (SQlConn.State == ConnectionState.Closed || SQlConn.State == ConnectionState.Broken) 
         SQlConn.Open(); 
        bulkCopy.WriteToServer(dt1); 
        SQlConn.Close(); 
        SQlConn.Dispose(); 
        bulkCopy.Close(); 
        if (bulkCopy != null) 
        { 
         ((IDisposable)bulkCopy).Dispose(); 
        }       
       } 

      } 

      dtDestination.Dispose(); 
      System.GC.Collect(); 
      dtDestination = null; 
     } 
     catch (Exception ex) 
     { 
      Logger.Log(ex, Logger.LogType.Error); 
      throw ex; 

     } 
+0

您是使用一個大的數據表,還是每次爲每個10,000行提供相同的數據表或爲每個10,000行創建一個新的數據表?如果它是第三個,你應該嘗試每次調用dt1.Clear。 SqlBulkCopy不太可能導致這個問題 - 它很可能是數據表中的數據。請注意,不需要調用bulkCopy.Dispose() - 這將在您退出使用塊時完成。 – dash

+0

DataTable對象會發生什麼情況? –

+0

什麼是數據的來源,這裏有很多相關的代碼缺失。 –

回答

9

這裏的關鍵問題是:什麼是dt1,它是在哪裏來的,和你怎麼樣發佈了嗎? DataTable實際上很難清理,坦率地說,我通常不會在這裏推薦DataTable源代碼。但是,如果您需要必須使用DataTable,那麼確保每次迭代使用一個完全獨立的DataSet/DataTable,然後釋放舊的,以便可以循環使用。

但是,更高效的是使用WriteToServer(IDataReader) - 這允許您以流式處理行。如果您在兩個SQL系統之間進行復制,您甚至可以在單獨的命令/連接上使用ExecuteReader(),但IDataReader非常簡單,您可以爲大多數源編寫基本的IDataReader(或查找這樣做的庫,例如CsvReader處理分隔文件,如csv/tsv)。

+0

Dt1不過是我們插入的數據表。不,我們正在處理dt1。 以下是我們的代碼 – sunshine

1

我想這個問題是這一行:

bulkCopy.BatchSize = dt1.Rows.Count; 

的BatchSize屬性決定了有多少行被插入在一個內部事務。這裏的行大小可能是無限的。

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.batchsize.aspx

嘗試將其設置爲一個小而固定的數量應該解決的問題:

bulkCopy.BatchSize = 1000; 

它是由你來這裏決定最優批量大小。

+0

@Kamil Krasinski:我們正在部署dt1數據表對象。我們還需要發佈它嗎? – sunshine

+0

請讓我們知道我們可以給BatchSize的最大限制。我們可以放棄10萬。 ? – sunshine

+0

您可能希望將其設置爲null以釋放內存。我不認爲處置是有用的,因爲DataTable不包含任何非託管資源。 – xing