2011-10-02 76 views
0

我有n个csv文件,我需要对其进行比较并在之后进行修改。 问题是每个csv文件都有大约800.000行。将多个非常大的csv文件相互比较

要阅读csv文件,我使用fgetcsv,它的效果很好。获得一些记忆力,但最终它足够快。但是,如果我试图比较阵列彼此,它需要年龄。

另一个问题是,我必须使用foreach才能使用fgetcsv获取csv数据,因为有n个文件。我最终得到了一个超大数组,并且无法与array_diff进行比较。所以我需要将它与嵌套的foreach循环进行比较,并且需要很长时间。

代码段为更好地理解:

foreach($files as $value) { 
    $data[] = $csv->read($value['path']); 
} 

我的CSV类使用fgetcsv到输出添加到阵列:

fgetcsv($this->_fh, $this->_lengthToRead, $this->_delimiter, $this->_enclosure) 

所有的CSV文件中的每一个数据都存储在$数据阵列。这可能是仅使用一个数组的第一个大错误,但我不知道如何在不使用foreach的情况下保持对文件的灵活性。我试图使用灵活的变量名称,但我stucked在那里:)

现在我有这个大阵。通常,如果我尝试比较两个值,并确定文件2中的数据是否存在于文件2中等等,我使用array_diff或array_intersect。但在这种情况下,我只有这一个大阵。正如我所说的,对其进行陈述需要很长时间。

也只有3个文件后,我有一个数组3 * 800.000条目。我猜最新的10个文件后,我的记忆会爆炸。

那么有什么更好的方法来使用PHP来比较n个非常大的csv文件的数量?

+1

它是否必须是PHP?也许有一个命令行工具可以做到这一点?你如何准确地比较文件? –

+0

我是1980年的程序员 - 然后我们通过使用排序,然后一些逻辑来比较,然后结果第三个文件来解决它。有时候你会把工作分散到更小的块中 - 然后连续运行它们。 这不是一个解决方案,而是一种思考方式... – Mike

+0

将所有文件存储在一个数组中的要点是什么? –

回答

4

使用SQL

  • 具有相同的列的CSV文件创建一个表。
  • 从第一个CSV文件插入数据。
  • 添加索引以加快查询速度。
  • 通过阅读一行并发出SELECT来与其他CSV文件进行比较。

你没有描述你如何比较n个文件,并且有几种方法可以这样做。如果您只想查找A1中的行,而不是A2,...,An,那么您只需在表中添加布尔列diff。如果您想知道某行重复哪些文件,您需要一个文本列或一个新表,如果一行可以包含多个文件。

编辑:如果您使用MySQL,我会对其性能加以说明(我现在对其他RDBMS的了解不多)。

逐行插入行会太慢。除非您可以将CSV文件直接放入数据库服务器的文件系统,否则您可能无法使用LOAD DATA。所以我想最好的解决方案是在CSV中读取几百行,然后发送一个多重插入查询INSERT INTO mytable VALUES (..1..), (..2..)

对于在其他文件中读取的每一行,您都不能发出SELECT,因此最好将它们放在另一个表中。然后发出多表更新以标记表t1和t2中相同的行:UPDATE t1 JOIN t2 ON (t1.a = t2.a AND t1.b = t2.b) SET t1.diff=1

也许你可以尝试使用sqlite。这里没有并发问题,它可能比MySQL的客户端/服务器模型更快。你不需要设置太多的使用sqlite。

+0

谢谢。我需要比较A1在文件2/3/4中的任何位置等等。我想我会尝试一个临时数据库 – Talisin

+0

是的,我使用LOAD DATA来导入csv。它仍然很慢,但现在确定。多谢,伙计。 – Talisin