2013-02-04 32 views
0

可能重複:
How to efficiently write to file from SQL datareader in c#?慢,大型SQL從C#/ ASP.NET查詢

我目前正在創建使用只讀訪問,以允許用戶在Web應用程序從我們的數據庫下載大文件。有問題的表中有400,000條記錄,並在導出時生成50 MB .csv文件。

大約需要7秒運行語句「SELECT * FROM [表]」 SQL服務器上,並約33S從我的web應用程序(託管在不同的服務器上),這樣做的。這是將所有數據讀取到System.Data.SqlClient.SqlDataReader對象中。

我的問題是,我在爲我的SqlDataReader對象轉換爲.csv文件丟失。將SqlDataReader的每一行轉換爲一個字符串並將該字符串逐行輸出到一個文件需要近2個小時,這是不可接受的。以下是我用於在Web應用程序的服務器上創建文件的代碼:

while (rdr.Read()) 
    { 
     string lineout = ""; 
     for (int index = 0; index < rdr.FieldCount; index++) 
      lineout += rdr[index].ToString().Replace(',', ' ') + ','; 
     write(lineout, filename); //uses StreamWriter.WriteLine() 
    } 

必須有更好的方法。我環顧四周,看到很多建議,基本上建議做上述創建一個文件。這對於較小的桌子很有效,但不是我們每天使用的兩個非常大的桌子。任何人都可以給我一個正確的方向?

+0

你確定它不是很慢的SQL嗎? – SLaks

+0

http://stackoverflow.com/questions/9055521/how-to-efficiently-write-to-file-from-sql-datareader-in-c – samuelesque

+0

假設你的服務器上運行這個?運行查詢時機器的性能如何反應?你在哪裏使用數據集? –

回答

5

你可以嘗試構建lineoutStringBuilder而不是手動連接字符串:

//you can test whether it makes any difference in performance declaring a single 
//StringBuilder and clearing, or creating a new one per loop 
var sb = new StringBuilder(); 

while (rdr.Read()) 
{ 
    for (int index = 0; index < rdr.FieldCount; index++) 
     sb.Append(rdr[index].ToString().Replace(',', ' ').Append(','); 

    write(sb.ToString(), filename); //uses StreamWriter.WriteLine() 
    sb.Clear(); 
} 

或者嘗試只寫入文件直接和避免產生存儲器中的每一行第一:

//assume a StreamWriter instance has been created called sw... 
while (rdr.Read()) 
{ 
    for (int index = 0; index < rdr.FieldCount; index++) 
    { 
     sw.Write(rdr[index].ToString().Replace(',', ' '); 
     sw.WriteLine(","); 
    } 
} 

//flush and close stream 
+0

肯定的,使用StringBuilder比連接字符串更有效。沒有無用的內存分配,沒有多餘的內存碎片,好點(我投票) – Adi

+0

第二種方法是我使用的。雖然我這樣做是爲了讓它被引用分隔和逗號分隔。 'sw.Write( 「\」{0} \ 「{1}」,RDR [指數],索引== rdr.FieldCount - 1 「」: 「」);'然後我不必擔心逗號的價值觀和我的情況我已經知道有沒有'「'的字符串,我也不必調用toString() –

+1

你是一個美麗的人,丹尼爾。謝謝!使用您所提供的StreamWriter的代碼,執行時間不到40s。 – wmaynard