Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在PHP中从DB输出编写非常大的CSV文件_Php_Mysql_Csv - Fatal编程技术网

在PHP中从DB输出编写非常大的CSV文件

在PHP中从DB输出编写非常大的CSV文件,php,mysql,csv,Php,Mysql,Csv,我有每秒收集的传感器数据的DB。客户希望能够下载CSV格式的12小时区块-这一切都完成了 遗憾的是,输出不是直接的数据,需要在创建CSV之前进行处理(部分以JSON的形式存储在数据库中)-因此我不能只转储表 因此,为了减少负载,我认为第一次下载文件时,我会将其缓存到磁盘,然后任何其他请求都只需下载该文件 如果我不尝试写它(使用file\u put\u contents,file\u APPEND),只回显每一行就可以了,但是写它,即使我给脚本512M,它也会耗尽内存 所以这是可行的 while(

我有每秒收集的传感器数据的DB。客户希望能够下载CSV格式的12小时区块-这一切都完成了

遗憾的是,输出不是直接的数据,需要在创建CSV之前进行处理(部分以JSON的形式存储在数据库中)-因此我不能只转储表

因此,为了减少负载,我认为第一次下载文件时,我会将其缓存到磁盘,然后任何其他请求都只需下载该文件

如果我不尝试写它(使用file\u put\u contents,file\u APPEND),只回显每一行就可以了,但是写它,即使我给脚本512M,它也会耗尽内存

所以这是可行的

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,请提供该文件。