繁体   English   中英

从PHP的DB输出编写一个很大的CSV文件

[英]Writing a very large CSV file From DB output in PHP

我有一个每秒收集一次的传感器数据数据库。 客户端希望能够以CSV格式下载12小时的数据块-全部完成。

遗憾的是,输出的数据不是笔直的数据,需要先进行处理,然后才能创建CSV(部分以JSON格式存储在数据库中)-因此我不能只转储表。

因此,为了减少负载,我认为第一次下载文件时,我会将其缓存到磁盘上,然后再有其他请求就下载该文件。

如果我不尝试编写它(使用file_put_contents,FILE_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_put_contents,它将全部存储到内存中。

有什么建议么?

问题在于file_put_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);
}

这将限制在任何给定时间试图丢入数据中的数据量。

我完全同意一次写入一行,因此您永远不会遇到这种内存问题,因为一次最多只能加载1行。 我有一个做同样的应用程序。 但是,我发现此方法存在一个问题,就是文件要花很长时间才能完成写入。 因此,本文旨在支持已经说过的内容,同时也请大家就如何加快此操作提出意见。 例如,我的系统针对抑制文件清除数据文件,因此我一次读入一行并在抑制文件中查找匹配项,然后如果找不到匹配项,则将该行写入新的清理文件中。 一个50k的线路文件大约需要4个小时才能完成,所以我希望找到一个更好的方法。 我已经尝试了几种方法,现在我将整个抑制文件加载到内存中,以避免我的主读取循环不得不在抑制文件的每一行中运行另一个循环,但是即使这样仍然要花费数小时。

因此,到目前为止,逐行是管理系统内存的最佳方法,但是我想获得一个50k行文件(行是电子邮件地址以及姓氏和名字)的处理时间,以使运行时间少于30分钟,如果可能的话。

仅供参考:抑制文件的大小为16,000 kb,如memory_get_usage()所告诉,脚本使用的总内存约为35兆。

谢谢!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM