我有 n 个 csv 文件,我需要相互比较并在之后修改它们。问题是每个 csv 文件大约有 800.000 行。
要读取 csv 文件,我使用fgetcsv并且效果很好。获得一些内存矛,但最终它足够快。但是,如果我尝试将数组相互比较,则需要很长时间。
另一个问题是我必须使用 foreach 来通过 fgetcsv 获取 csv 数据,因为有 n 个文件。我最终得到了一个超大数组,无法与 array_diff 进行比较。所以我需要将它与嵌套的 foreach 循环进行比较,这需要很长时间。
一个代码片段,以便更好地理解:
foreach( $files as $value ) {
$data[] = $csv->read( $value['path'] );
}
Run Code Online (Sandbox Code Playgroud)
我的 csv 类使用 fgetcsv 将输出添加到数组中:
fgetcsv( $this->_fh, $this->_lengthToRead, $this->_delimiter, $this->_enclosure )
Run Code Online (Sandbox Code Playgroud)
所有 csv 文件的每个数据都存储在 $data 数组中。这可能是只使用一个数组的第一个大错误,但我不知道如何在不使用 foreach 的情况下保持文件的灵活性。我尝试使用灵活的变量名,但我也坚持使用:)
现在我有这个大数组。通常,如果我尝试将这些值相互比较并找出文件 1 中的数据是否存在于文件 2 中等等,我会使用 array_diff 或 array_intersect。但在这种情况下,我只有这个大数组。正如我所说,运行 foreach 需要很长时间。
同样在只有 3 个文件之后,我有一个包含 3 * 800.000 个条目的数组。我猜最近 10 个文件后我的记忆会爆炸。
那么有没有更好的方法来使用 PHP 来比较 n 个非常大的 csv 文件?
小智 5
使用 SQL
您没有描述如何比较 n 个文件,有几种方法可以这样做。如果您只想找到 A1 中而不是 A2,...,An 中的行,那么您只需在表中添加一个布尔列diff。如果您想知道一行在哪些文件中重复,则需要一个文本列,或者如果一行可以在多个文件中,则需要一个新表。
编辑:如果您使用 MySQL,请谈谈性能(我现在不太了解其他 RDBMS)。
一行一行地插入行会太慢。LOAD DATA除非您可以将 CSV 文件直接放入数据库服务器的文件系统,否则您可能无法使用。所以我想最好的解决方案是读取 CSV 中的几百行,然后发送多个插入查询INSERT INTO mytable VALUES (..1..), (..2..)。
您不能SELECT为您在其他文件中读取的每一行发出 a ,因此您最好将它们放在另一个表中。然后发出多表更新以标记表 t1 和 t2 中相同的行:UPDATE t1 JOIN t2 ON (t1.a = t2.a AND t1.b = t2.b) SET t1.diff=1
也许您可以尝试使用 sqlite。这里没有并发问题,它可能比 MySQL 的客户端/服务器模型更快。而且您不需要设置太多就可以使用 sqlite。
| 归档时间: |
|
| 查看次数: |
1656 次 |
| 最近记录: |