將大量數據從CSV(300萬行+)加載到數據庫的最有效方法是什麼?C#將大量數據從CSV導入到數據庫
- 的數據需要被格式化(例如名稱列需要被分成第一名和姓等)
- 我需要做這在高效地即時間限制
我正在閱讀,使用C#應用程序逐行讀取,轉換和加載數據?這是理想的,如果不是,我的選擇是什麼?我應該使用多線程嗎?
將大量數據從CSV(300萬行+)加載到數據庫的最有效方法是什麼?C#將大量數據從CSV導入到數據庫
我正在閱讀,使用C#應用程序逐行讀取,轉換和加載數據?這是理想的,如果不是,我的選擇是什麼?我應該使用多線程嗎?
您將被I/O綁定,因此多線程不一定會使其運行速度更快。
上次我做到了這一點,它大概有十幾行C#。在一個線程中,它以儘可能快的速度運行硬盤,因爲它可以從盤片中讀取數據。我一次從源文件中讀取一行。
如果你不喜歡自己寫,你可以試試FileHelpers庫。您可能還想看看Sébastien Lorion's work。他的CSV閱讀器專門用於處理性能問題。
是的,c#io庫的緩衝區很好。最近我不得不在一分鐘內從一個csv轉換到另一個(1.5米線)。 – 2010-04-14 22:46:03
我也推薦FileHelpers。它使我不必編寫解析器來處理其中包含逗號的值。如果CSV有任何這樣令人討厭的細節,請考慮FileHelpers。 – 2010-04-14 22:49:18
我知道在過去,驅動器上的尋找時間是一個問題。在大圖像文件的情況下,我們將從一個驅動器讀取數據並寫入另一個驅動器,以減少重新定位驅動器磁頭的次數。 – yamspog 2010-04-14 23:03:02
我同意你的解決方案。一次讀取一行文件應避免一次將整個文件讀入內存的開銷,這應該使應用程序快速高效地運行,主要是花時間從文件中讀取(這相對較快)並解析行。我注意的一點是要注意你的CSV中是否嵌入了換行符。我不知道您使用的具體CSV格式是否可能實際上在數據中的引號之間輸出換行符,但當然可能會混淆該算法。我想建議在將它們發送到數據庫之前將插入語句(在一個字符串中包括許多插入語句)批量化,如果這在檢索您需要用於後續外鍵的生成的鍵值時不存在問題(希望你不需要檢索任何生成的鍵值)。請記住,SQL Server(如果這就是你所使用的)每批只能處理2200個參數,所以限制你的批量大小來解決這個問題。我建議使用參數化的TSQL語句來執行插入操作。我懷疑插入記錄需要花費更多的時間,而不是從文件中讀取它們。
你沒有說明你正在使用哪個數據庫,但考慮到你提到的語言是C#我將假設SQL Server。
如果無法使用BCP導入數據(如果需要大量處理,聽起來好像不行),那麼SSIS很可能是下一個最快的選項。它不是世界上最好的開發平臺,但速度非常快。肯定比任何可以在任何合理時間內自行編寫的應用程序都快。
我與Greg和JayRiggs合作。跳過C#(除非您正在爲SQL Server編寫CLR模塊)。讓SQL完成這項工作。如果您沒有聽說過,那麼從文件中處理大量數據是非常好的。 ;)這會爲您節省打開conxns等各種令人頭疼的問題。 – jcolebrand 2010-04-14 22:52:38
這使得單元測試非常困難? – guazz 2010-04-14 23:26:13
這實際上並不是單元測試非常有用的問題。人們過多地關注單元測試,忽視更大的圖景。你應該測試的是,如果已知CSV數據集,那麼進入數據庫的數據是正確的,並且按預期處理已知壞的情況(固定的,丟棄的或失敗的)。如果你這樣做,那麼它如何進入數據庫並不重要。所以從任何實際角度來看,我都會說SSIS和其他任何東西一樣可測試。 – 2010-04-15 11:26:20
您可以使用csvreader來快速讀取CSV。
假設您正在使用SQL Server,您可以使用csvreader的CachedCsvReader
將數據讀取到DataTable中,您可以使用該數據表將SqlBulkCopy加載到SQL Server中。
這就是我使用的。我喜歡csvreader,它是訪問分隔文件的一種非常方便的方式。 – galford13x 2010-04-14 23:12:25
+1爲SqlBulkCopy – Kiril 2010-04-14 23:41:35
BCP非常快,所以我會用它來加載數據。對於字符串操作,一旦數據在那裏,我會在SQL上使用CLR函數。除了增加複雜性並損害性能之外,多線程無助於這種情況。
將CSV文件的內容逐行讀入內存DataTable中。隨着DataTable的填充,您可以操作數據(即:分割名字和姓氏)等。
將CSV數據加載到內存後,使用SqlBulkCopy將數據發送到數據庫。
查看http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.writetoserver.aspx的文檔。
如果你真的想在C#中做到這一點,創建&填充一個DataTable,截斷目標數據庫表,然後使用System.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable dt)。
不幸的是,我需要更新現有的記錄,數據將每天加載。 – guazz 2010-04-14 23:27:17
時間限制有多嚴格? – Jake 2010-04-14 22:54:11