搜索1GB的CSV文件



我有一个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万条记录。我刚试着在我的双核Win 32位笔记本电脑上加载这个,在调试中有4GB内存,它抛出了一个OutOfMemoryException

我现在认为不将文件加载到内存将是最好的选择,但需要找到一种方法来快速搜索文件,看看输入数据是否有一个匹配的项目等于element[27],然后在CSV中取前24个元素,并将其与输入数据进行比较。

a)即使我坚持这种方法并使用16GB RAM和Windows 64位,那么在字典中有那么多条目是可以的吗?

b)如果你不认为使用字典是一个好的计划,你能提供一些代码/链接来快速搜索CSV文件吗

UPDATE:虽然我已经接受了答案,但我只是想知道人们对使用FileStream进行查找然后提取数据的想法

如果你打算搜索这么多的记录,我建议将文件批量插入到DBMS中,如SQL Server,并为您的标准字段提供适当的索引,然后使用SQL查询来检查记录的存在。

在导入包含需要聚合的数据的大型csv文件时遇到了类似的问题。最后,我们对SQL Server表进行了批量插入,并使用SQL来执行聚合。最后还蛮快的(端到端只用了几分钟)。

有几个选项可供您使用,但是是的,我同意将此数据加载到内存中不是最佳选择。

a)您可以将数据加载到关系数据库中,尽管这对于这种类型的数据来说可能有些多余。

b)你可以使用像RavenDB这样的NoSQL解决方案。我想这对你来说可能是个不错的选择。

c)你可以使用更有效的物理存储选项,如Lucene

d)你可以使用更高效的内存/缓存选项,如Redis。

解决方案可以是将文件分解为一些较小的文件,并在每个文件中并行搜索搜索顺序应该小于或等于n(读取整个文件)

由于程序的其余部分使用StringDictionary条目,理想情况下仍然需要将结果存储在内存中—您真的不希望查询到DB的次数达到1000次。(这可能取决于您的程序是否在DB服务器上)!

我会为你的结构查看StringDictionary的内存使用情况,看看你的理论最大值是多少,看看你是否可以在功能需求的警告中涵盖这一点。否则,寻找一种更有效的存储方式——例如,将结果流式传输到XML文件将比访问DB更快。

  • 忘记MS访问。真的。
  • 尝试sqlite,它将足以满足几百万行
  • 如果您不能索引您的数据,那么不要使用数据库,使用外部实用程序,如egrep和适当的正则表达式来搜索特定字段。这会快得多。

最新更新