在PHP中从DB输出编写非常大的CSV文件
我有每秒收集的传感器数据的DB。客户希望能够下载CSV格式的12小时区块-这一切都完成了 遗憾的是,输出不是直接的数据,需要在创建CSV之前进行处理(部分以JSON的形式存储在数据库中)-因此我不能只转储表 因此,为了减少负载,我认为第一次下载文件时,我会将其缓存到磁盘,然后任何其他请求都只需下载该文件 如果我不尝试写它(使用file\u put\u contents,file\u APPEND),只回显每一行就可以了,但是写它,即使我给脚本512M,它也会耗尽内存 所以这是可行的在PHP中从DB输出编写非常大的CSV文件,php,mysql,csv,Php,Mysql,Csv,我有每秒收集的传感器数据的DB。客户希望能够下载CSV格式的12小时区块-这一切都完成了 遗憾的是,输出不是直接的数据,需要在创建CSV之前进行处理(部分以JSON的形式存储在数据库中)-因此我不能只转储表 因此,为了减少负载,我认为第一次下载文件时,我会将其缓存到磁盘,然后任何其他请求都只需下载该文件 如果我不尝试写它(使用file\u put\u contents,file\u APPEND),只回显每一行就可以了,但是写它,即使我给脚本512M,它也会耗尽内存 所以这是可行的 while(
while($stmt->fetch()){
//processing code
$content = //CSV formatting
echo $content;
}
这不是
while($stmt->fetch()){
//processing code
$content = //CSV formatting
file_put_contents($pathToFile, $content, FILE_APPEND);
}
好像我在每一行调用file\u put\u contents,它将所有内容存储到内存中
有什么建议吗?问题是文件内容试图一次转储整个内容。相反,您应该在格式中循环使用fopen、fwrite和fclose
while($stmt->fetch()){
//processing code
$content[] = //CSV formatting
$file = fopen($pathToFile, a);
foreach($content as $line)
{
fwrite($file, $line);
}
fclose($file);
}
这将限制在任何给定时间尝试在数据中抛出的数据量。我完全同意一次只写一行,这样就不会有内存问题,因为一次加载到内存中的行永远不会超过一行。我有一个同样的应用程序。然而,我发现这个方法的一个问题是,文件需要花费很长时间才能完成编写。所以这篇文章是为了支持已经说过的话,也是为了征求大家对如何加快这一进程的意见?例如,我的系统根据抑制文件清理数据文件,因此我一次读取一行,并在抑制文件中查找匹配项,如果未找到匹配项,则将该行写入新清理的文件。一个50k行文件需要大约4个小时才能完成,所以我希望找到一个更好的方法。我尝试了几种方法,现在我将整个抑制文件加载到内存中,以避免我的主读取循环必须在抑制文件中的每一行运行另一个循环,但即使这样也需要几个小时 因此,逐行管理是目前管理系统内存的最佳方式,但我希望能够在30分钟内完成50k行文件(行是电子邮件地址和名字和姓氏)的处理时间,如果可能的话 仅供参考:抑制文件的大小为16000 kb,根据memory_get_usage()的说明,脚本使用的总内存约为35兆
谢谢 您是否尝试过使用fwrite()逐行编写它?虽然本质上是正确的,但请注意在原始版本中如何使用
echo$content
,因此它只是$content=//CSV格式;fwrite($file,$content)
并将fopen
和fclose
移出主循环。是否确实需要始终打开和关闭文件?否则我同意,尝试使用fwrite.Race条件一次在线写入文件。有人吗?如果第二个用户加载此文件,而另一个用户仍在等待加载该文件,该怎么办?我认为数据损坏是可能的,甚至是可能的,因为在办公环境中,用户可能会同时看到这样的东西。@sakatt然后我会缓存该文件,因此如果有一个文件不超过X,请提供该文件。