用C ++处理大量数据需要方法

时间:2014-03-20 18:19:13

标签: c++ sqlite stxxl large-data

所以我有一个像这样的CSV格式的1GB文件,我转换为SQLite3数据库

column1;column2;column3
1212;abcd;20090909
1543;efgh;20120120

除了我有12列。现在,我需要读取和排序这些数据并重新格式化输出,但是当我尝试这样做时,似乎我的RAM耗尽(使用向量)。我从SQLite中读取它并将文件的每一行存储在一个结构中,然后将其推回到双端队列中。就像我说的,当RAM使用量接近2GB时,我的内存耗尽,应用程序崩溃了。我尝试使用STXXL,但显然它不支持非POD类型的向量(所以它必须是long int,double,char等),而我的vector主要由std :: string' s组成,有些是boost ::日期和一个双倍值。

基本上我需要做的是将所有"行"在特定列中具有相同值的一起,换句话说,我需要基于一列对数据进行排序,然后使用它。

关于我如何阅读所有内容或至少对其进行排序的任何方法?我会用SQLite3来做,但这似乎很耗时。也许我错了。

感谢。

5 个答案:

答案 0 :(得分:1)

为了满足需求:

  1. 根本不使用C ++,如果可能,只使用sort
  2. 如果您坚持使用数据库来处理一个非常大的csv文件,听起来像是一种非常关系的方式,那么将所有繁重的工作转移到数据库中,让它担心内存管理。
  3. 如果你必须在C ++中这样做:
    • 完全跳过SQLite3步骤,因为您没有使用它。只需将csv文件映射到内存中,然后构建行指针向量。在不移动数据的情况下对进行排序
    • 如果必须将行解析为结构:
      • 不要将字符串列存储为std::string - 这需要额外的非连续分配,这会浪费内存。如果长度有界,则首选内联字符数组
      • 选择适合您的值的最小整数大小(例如,uint16_t适合您的样本第一列值)
      • 注意填充:检查结构的大小,重新排序成员或如果它比预期的大得多,请将其打包

答案 1 :(得分:1)

如果你想坚持使用SQLite3方法,我建议使用列表而不是矢量,这样你的操作系统就不需要找到1GB或更多的连续内存。

如果您可以跳过SQLite3步骤,以下是解决问题的方法:

  1. 编写一个类(例如MyRow),其中包含数据集中每列的字段。
  2. 将文件读入std::list<MyRow>,其中数据集中的每一行都成为MyRow的实例
  3. 编写一个比较所需列的谓词
  4. 使用std :: list的sort函数对数据进行排序。
  5. 我希望这会对你有所帮助。

答案 2 :(得分:0)

std::string的开销很大。如果您的struct每列包含std::string,则会在char *指针,malloc标题等上浪费大量空间。

尝试在阅读文件时立即解析所有数字字段,并将其作为ints或您需要的任何内容存储在结构中。

如果您的文件实际上包含很多数字字段,例如您的示例节目,我希望它在解析后使用 less 而不是文件大小的内存。

答案 3 :(得分:0)

为您的记录创建结构。

记录应该有&#34;命令&#34;您需要排序的字段的函数。

将文件作为对象读取并存储到具有随机访问功能的容器中,例如std::vectorstd::array

对于要排序的每个字段: 创建索引表std::map,使用字段值作为键,将记录索引作为值。

要按顺序处理字段,请选择索引表并遍历索引表。使用值字段(a.k.a. index)从对象容器中获取对象。

如果记录具有固定长度或可以转换为固定长度,则可以将二进制对象写入文件并将文件定位到不同的记录。使用索引表,如上所述,除了使用文件位置而不是索引。

答案 4 :(得分:0)

感谢您的回答,但我想出了一种非常快速而简单的方法。

我让SQLite3通过给它这个查询来完成这项工作:

SELECT * FROM my_table ORDER BY key_column ASC

对于一个800MB的文件,大约需要70秒来处理,然后我收到了我的C ++程序中的所有数据,已经按照我希望它们分组的列进行排序,我一次处理了一个组,并以我想要的输出格式一次输出一个,保持我的RAM不会过载。手术总时间约为200秒,我非常满意。

感谢您的时间。