【问题标题】:Comparing multiple very large csv files against each other比较多个非常大的 csv 文件
【发布时间】:2011-10-02 11:19:46
【问题描述】:

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

要读取 csv 文件,我使用 fgetcsv 并且效果很好。获得一些记忆棒,但最终它已经足够快了。但是,如果我尝试将数组相互比较,则需要很长时间。

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

一个代码 sn-p 以便更好地理解:

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。但在这种情况下,我只有一个大数组。正如我所说,运行一个 foreach 需要很长时间。

在只有 3 个文件之后,我有一个包含 3 * 800.000 个条目的数组。我猜最近 10 个文件后我的记忆会爆炸。

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

【问题讨论】:

  • 必须是 PHP 吗?也许有一个命令行实用程序可以做到这一点?您如何准确比较文件?
  • 我是 1980 年的程序员' - 然后我们通过使用排序解决了它,然后是一些逻辑进行比较,然后是第三个文件与结果。有时,您将作业拆分成更小的块 - 然后连续运行它们。这不是一个解决方案,而是一种思维方式......
  • 将所有文件存储在一个数组中的意义何在?
  • 我需要将它们相互比较并从中生成一个新数组,我对其进行修改并通过 API 发送它。所以最后,我需要它返回给 PHP 的 API。 @Col。正如我所说,重点是我不知道如何拆分它并保持灵活性:)
  • 数据必须是 CSV 格式吗?为什么不将其导入数据库?大多数 DBMS 都支持将 CSV 文件轻松导入表中,一旦将其导入表中,您就可以对数据运行查询以进行比较。

标签: php csv fgetcsv


【解决方案1】:

使用 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。

【讨论】:

  • 谢谢。我需要比较 A1 是否在文件 2/3/4 中的任何位置等等。我想我会尝试使用临时数据库
  • 是的,我使用 LOAD DATA 导入 csv。它仍然很慢,但现在还可以。谢谢老兄。
猜你喜欢
  • 1970-01-01
  • 2013-05-07
  • 1970-01-01
  • 1970-01-01
  • 2020-03-22
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 2019-01-19
相关资源
最近更新 更多