2011-11-10 74 views
2

我有一個CSV文件。每一行是由相同的格式例如/搜索1GB CSV文件

I,h,q,q,3,A,5,Q,3,[,5,Q,8,c,3,N,3,E,4,F,4,g,4,I,V,9000,0000001-100,G9999999990001800000000000001,G9999999990000001100PDNELKKMMCNELRQNWJ010, , , , , , ,D,Z, 

我有一個Dictionary<string, List<char>>

它通過打開文件,讀每一行,從行服用元件並將其添加到詞典中填入,那麼文件關閉。

該字典用於程序中的其他地方,它接受輸入數據到程序中,然後在字典中找到鍵並使用24個元素與輸入數據進行比較。

StreamReader s = File.OpenText(file); 
string lineData = null; 
while ((lineData = s.ReadLine()) != null) 
{ 
    var elements = lineData.Split(','); 
    //Do stuff with elements 
    var compareElements = elements.Take(24).Select(x => x[0]); 
    FileData.Add(elements[27], new List<char>(compareElements)); 

    } 
    s.Close(); 

我剛纔被告知CSV文件現在是800MB,並且其中有大約800萬條記錄。我剛剛嘗試在調試中裝載4GB內存的Dual Core Win 32bit筆記本電腦上加載它,並且它投擲了一個OutOfMemoryException

我現在認爲不將文件加載到內存中將是最好的選擇,但需要找到一種快速搜索文件的方式,以查看輸入數據是否具有匹配的項目等於element[27],然後將第24項該CSV中的元素並將其與輸入數據進行比較。

a)即使我堅持使用這種方法,並使用16GB內存和Windows 64位將有一個字典中的許多項目是好的?

b)您能否提供一些代碼/鏈接的方式來搜索一個CSV迅速文件,如果你不使用詞典認爲這是一個很好的計劃

UPDATE:雖然我已經接受一個答案,我只是想知道什麼人的想法是使用FileStream進行查找然後提取數據。

+6

沒有答案,只是一個建議:使用數據庫,而不是一個CSV文件!如果你需要單一的數據庫文件,SQLite是你的唯一。 – Marco

+0

將1GB數據存入內存絕對不是一個明智的選擇。您可能不希望程序耗盡所有可用RAM。改用DBMS。 – Raptor

+0

@Marco你是說創建的數據庫文件是一個文件?如果是這樣,我假設我可以通過創建一個新的DB文件並刪除任何舊文件來將CSV文件導入到數據庫中? – Jon

回答

4

如果您打算搜索這麼多記錄,我會建議將文件批量插入到像SQL Server這樣的DBMS中,並將相應的字段索引作爲您的條件,然後使用SQL查詢來檢查有記錄。

+0

通常我會同意,但是這個程序要發給沒有IT知識的客戶,並且將大量數據導入到數據庫中需要管理我的感受 – Jon

+0

然後嘗試使用簡單的DBMS如MS Access。即使這可以幫助很大。 – Maheep

+0

但是系統應該將它載入DMBS本身......作爲讀取文件的第一部分。問題可能會創造一個最佳的結構。 如果你可以使用一些像SQLite這樣的小型lightwieght數據庫,這可能是最簡單的 – Holger

0

我們在導入包含需要聚合的數據的大型csv文件時遇到類似問題。最後,我們對SQL Server表進行了批量插入,並使用SQL來執行聚合。最後很快(幾分鐘端對端)。

+0

糟糕,剛纔意識到我重複了Ioannis的回答......那麼一定是個好主意。 – Simon

0

有幾種選擇可供選擇,但是,我同意將這些數據加載到內存中並不是最佳選擇。

a)您可以將數據加載到關係數據庫中,儘管這可能對這種類型的數據過度。

b)您可以使用NoSQL解決方案,如RavenDB。我認爲這對你來說可能是一個不錯的選擇。

c)你可以使用像Lucene

d更高效的物理存儲選項),你可以使用更高效的內存/緩存選項像Redis

0

一個解決方案可以在文件中打破一些較小的文件,做每個文件 搜索的順序將是小於或等於n並行搜索(讀取整個文件)

+0

你能演示一個例子嗎? – Jon

+0

好吧,如果你有1 GB的數據文件將它分爲10個文件100毫克,然後當用戶serachs運行創建10線程runasearch命令在每個文件中的第一個保證,你可以停止整個搜索,並停止它 – DeveloperX

+0

對不起,我的意思是代碼明智的 – Jon

0

由於程序使用的其他StringDictionary條目,你仍然理想的需要將結果存儲在內存中 - 你並不真正想要查詢DB 1000的時間。 (這可能取決於您的程序是否位於數據庫服務器上)!

我會研究你的結構的StringDictionary的內存使用情況,看看你的理論上的最大值是什麼,看看你是否可以在功能需求的一個警告覆蓋這個。否則,尋找更有效的存儲方式 - 例如,將結果輸出到XML文件比訪問數據庫更快。

+0

不完全理解你的答案,但如果我發現文件/字典和輸入數據之間的匹配,我正在寫一個UniqueID,通過/失敗字符串到一個新文件 – Jon

+0

你已經聲明「該字典在程序中的其他地方使用「所以我認爲這就是爲什麼你想保存在內存中?如果有很多訪問這個中間字典,你不希望這些訪問跨越可能很慢的數據庫鏈接。 – Paul

+0

好點。它在我的比較中只能訪問3次 – Jon

0
  • 忘記MS訪問。真。
  • 嘗試sqlite,它將超過足夠的幾百萬行
  • 如果你不能索引你的數據,那麼不要使用數據庫,使用外部工具,如egrep與適當的正則表達式來搜索特定領域。它會更快。