首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >加快CSV文件的处理速度

加快CSV文件的处理速度
EN

Stack Overflow用户
提问于 2011-05-22 19:47:10
回答 3查看 1.2K关注 0票数 10

我有一个项目,我必须提高它的性能。我有一个由一个巨大的CSV文件(1亿行)构建的大型Mysql数据库。插入时间不是问题,但是请求的响应时间非常重要,有时带有2个join的查询大约需要20个小时.

为了缩短响应时间,我尝试将我的数据库迁移到Cassandra,但没有成功:我的数据模型不适合Cassandra概念。然后,我想尝试另一种提高性能的方法:并行Virutal文件系统。相反,在Mysql数据库中插入数据,然后发送查询,我尝试用多线程读取整个csv文件,并进行了计算。但结果不是很好:2m20只够1000行。

目前,我的计算非常简单:在使用MPI的C++中,我只从2列中计算不同对值的数目。为了实现这种计算,我使用了一个hashmap,其中每个键都是csv文件中的一对值。最后,返回hashmap大小。这里有一个小代码:

代码语言:javascript
复制
 MPI::Init(argc,argv); 
 cout << " INFO init done" << endl;
 int myrank = MPI::COMM_WORLD.Get_rank(); 
 int numprocs = MPI::COMM_WORLD.Get_size(); 
 get_filename(path_name, myrank);
 cout << " INFO open file : " << path_name << endl;
 MPI::File thefile = MPI::File::Open(MPI::COMM_WORLD, path_name.c_str(), 
                  MPI::MODE_RDONLY, 
                  MPI::INFO_NULL); 
 MPI::Offset offset = 101;
 MPI::Offset limit = thefile.Get_size();
 cout << " INFO go computing" << endl;
 do {
   thefile.Read_at(offset, buf, bufsize, MPI_CHAR, status);
   temp.assign(buf);
   Tokenize(temp,tokens,"\n");
   line.assign(tokens.at(0));
   tokens.clear();

   Tokenize(line,tokens,"\t");
   nidt_count(tokens);
   tokens.clear();
   offset += (line.size() + 1);
 }while(offset < limit);
 count = status.Get_count(MPI_INT);
 cout << "process " << myrank << " reads " << nidt_hash.size() << " nidt" << endl; 

我在一台服务器上工作,服务器有4个核心,8GB内存。我的数据在NFS或我服务器上的Samba中挂载的NAS上。我可以添加2或3台服务器进行处理,但目前我只是在一台服务器上尝试了一个小文件(100万行)来衡量性能。

最后,我的问题是:

对于我的问题,

  • 是一个很好的思考方式,可以改为PVFS类型吗?我想说的是,我将处理更复杂的查询,例如:选择具有特定日期(范围时间)的所有行,以及从特定列中选择特定的对值。
  • 您知道其他可以帮助我改进从csv文件中处理的东西吗?我正在考虑使用Hadoop、Pytables或FasterCSV.

这里是由2个csv文件组成的数据示例:

最大的一行(1亿行)组成如下:

代码语言:javascript
复制
ID        DATE             NUM_1        NUM_2     NB_UNITE TYPUNIT CODE_1 CODE_2

0  2007-05-13 15:37:48  33671624244  33698802900    547      s       0      17
0  2007-05-13 15:52:22  33671624244  33672211799      5      s       0      17 
....

第二个更简单、更小(9万),就像字典一样,我从一个code_1code_2中得到一个名为CODEVAL的值:

代码语言:javascript
复制
CODE_1 CODE_2 CODEVAL

  0       17     VS
  0       34     SS

正如您所预期的,通常我为每个文件创建两个表,一个典型的查询是:

代码语言:javascript
复制
Select CODEVAL, hour(date) AS HEURE, COUNT(*) AS NBSMSSOR 
From Tables_1 Join CODEVAL using(CODE_1,CODE_2) 
Where CODEVAL='SS'

对不起,我不知道如何制作数组。

这里是由2个csv文件组成的数据示例:

最大的

  • (1亿行)组成如下:

ID日期NUM_1 NUM_2 NB_UNITE TYPUNIT CODE_1 CODE_2

0 2007-05-13 15:37:48 33671624244 33698802900 547 s 0 17

0 2007-05-13 15:52:22 33671624244 33672211799 5 s 0 17…

  • 第二个更简单、更小(9万),就像字典一样,从code_1和code_2中得到一个名为CODEVAL的值:

CODE_1 CODE_2坐标

017比

0 34 SS

正如您所预期的,通常我为每个文件创建两个表,一个典型的查询是:

CODEVAL='SS'

  • 从Tables_1中选择CODEVAL,小时(日期)为HEURE,计数(*)为NBSMSSOR,使用(CODE_1,CODE_2)

对不起,我不知道如何制作数组。

EN

回答 3

Stack Overflow用户

发布于 2011-05-22 20:15:51

在我看来,你好像被我/O束缚住了。如果您的数据是通过网络进行的,这是没有帮助的。我怀疑,如果您只是添加更多的机器,那么您的性能将下降,因为额外的竞争。请记住,仍然只有一个主轴和一个HD头读取您的数据。对于MPI解决方案,我建议制作多个数据副本,并将它们放在服务器上。

对于MySQL,我听到你在说什么。我发现MySQL对joins的效率很低。在我看来,它可以在没有它们的情况下进行全表扫描。我记得MySQL在一个查询上占用了超过一分钟的时间,而Oracle所用的时间不到一秒钟。也许可以试试PostgreSQL?我不确定这是否更好。另一种方法可能是让db为您排序数据,这样您就可以在没有hashmap的情况下进行扫描。

除非你的记录是巨大的,否则1亿张记录应该不会那么糟糕。

票数 2
EN

Stack Overflow用户

发布于 2011-05-23 09:09:30

如果您从CSV读取数据,我想它不会更改太频繁。因此,您也可以在CSV数据上构造自己的索引,而不是将其加载到一般的数据库产品中。还是需要完全的SQL支持?

除此之外,您还提到要返回不同K,V对的数目。但是,您确实计算了实际的对。我不知道您是否需要它们用于其他目的,但您也可以得到这个数字作为# HashMap键x#区别值,而不需要实际构建一个。

假设您为每一个表格建立一个索引

代码语言:javascript
复制
value -> {r | r is a byteOffset of a row that has "value" in the index column}

您可以回答许多很多查询,特别是确定不同对的数量应该只需几毫秒。

我希望这个答案是有帮助的,因为我不知道还需要满足什么要求。这个解决方案的强大程度远远低于支持SQL的DB (尤其是插入将使内容变得更加复杂),但至少确定不同对的数量应该会快几个数量级。

票数 0
EN

Stack Overflow用户

发布于 2015-03-02 23:10:48

分治100个小型数据库应该要快得多。您可以决定如何拆分它--我目前使用的是每行第一个单词的第一个字符--使用拆分(),所以在曾经有一个巨大的慢DB的地方,现在有(A +a+0-9)62个较快的小型数据库。另一个优势是,笔记本电脑现在可以完成以前只有功能强大、价格昂贵的个人电脑才能完成的工作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6090315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档