比较多个非常大的csv文件

时间:2011-10-02 11:19:46

标签: php csv fgetcsv

我有n个csv文件,我需要相互比较并在之后修改它们。 问题是每个csv文件大约有800.000行。

要阅读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文件的每个数据都存储在$ data数组中。这可能是仅使用一个阵列的第一个大错误,但我不知道如何在不使用foreach的情况下保持文件的灵活性。我试图使用灵活的变量名称,但我也坚持在那里:)

现在我有了这个大阵容。通常,如果我尝试将值相互比较并找出文件一中的数据是否存在于文件二中,依此类推,我使用array_diff或array_intersect。但在这种情况下,我只有这一个大阵列。正如我所说的那样,经过一段时间就需要很长时间。

此外,仅3个文件后,我有一个包含3 * 800.000个条目的数组。我想最新的10个文件后我的内存会爆炸。

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

1 个答案:

答案 0 :(得分:4)

使用SQL

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

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

编辑:如果您正在使用MySQL,我会谈谈性能(我现在对其他RDBMS没有太多了解)。

逐个插入行会太慢。您可能无法使用LOAD DATA,除非您可以将CSV文件直接放在数据库服务器的文件系统上。所以我想最好的解决方案是在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。