2011-02-01 45 views
5

我有以下的(簡化)代碼,我想優化速度,其中:C#優化:插入2個億行到數據庫

long inputLen = 50000000; // 50 million 
DataTable dataTable = new DataTable(); 
DataRow dataRow; 
object[] objectRow; 
while (inputLen--) 
{ 
    objectRow[0] = ... 
    objectRow[1] = ... 
    objectRow[2] = ... 

    // Generate output for this input 
    output = ... 

    for (int i = 0; i < outputLen; i++) // outputLen can range from 1 to 20,000 
    { 
     objectRow[3] = output[i]; 
     dataRow = dataTable.NewRow(); 
     dataRow.ItemArray = objectRow; 
     dataTable.Rows.Add(dataRow); 
    } 
} 

// Bulk copy 
SqlBulkCopy bulkTask = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, null); 
bulkTask.DestinationTableName = "newTable"; 
bulkTask.BatchSize = dataTable.Rows.Count; 
bulkTask.WriteToServer(dataTable); 
bulkTask.Close(); 
我已經在試圖加快速度使用SqlBulkCopy的

,但它似乎分配給DataTable本身的值證明是緩慢的。

我不知道DataTable如何工作,所以我想知道如果我通過首先創建一個可重用的數組,然後將其分配給DataRow,然後將DataRow添加到DataTable中創建不必要的開銷?或者首先使用DataTable不是最優的?輸入來自數據庫。

我不在乎LOC,只是速度。任何人都可以提供一些建議嗎?

+0

對於示例實現,請查看`SimpleDataReader` [here](https://groups.google.com/group/microsoft.public.dotnet.languages.csharp/msg/b1d70b504cdee2ad?hl=en) – 2011-02-01 08:20:22

回答

13

對於這樣一個大表,您應改用

public void WriteToServer(IDataReader reader) 

方法。

這可能意味着你必須實現自己的一個「假」IDataReader接口與你的代碼(如果你'沒有從現有的IDataReader得到數據),但這樣,你會得到「流」從頭到尾,並將避免2億次循環。

0

你不應該在內存中構造整個數據表。使用WrtieToServer的這個overload,這需要DataRow的數組。只需將數據分塊即可。

+0

Isn'那種方法仍然在內存中構建它?而且,如果我沒有耗盡內存,是不是將它構建在最快的內存中? – 2011-02-01 08:13:11

+0

如果你一次只構造1k行而不是200m,那麼內存管理器將容易保存這樣大小的數據。除此之外,你幾乎可以肯定會在200M內存中保存記錄 – gor 2011-02-01 08:16:14

4

而不是在內存中保存一個巨大的數據表,我會建議實施一個IDataReader,它提供的數據作爲批量複製。這將減少將所有內容都保存在內存中的需求,因此應該有助於提高性能。