写入一个非常大的CSV文件从PHP以PHP格式输出

问题描述:

我有一个传感器数据的数据库,每秒收集一次。客户希望能够以CSV格式下载12小时的数据块 - 这一切都完成了。写入一个非常大的CSV文件从PHP以PHP格式输出

输出可悲的不是直的数据,需要在创建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在每一行,所以这一切存储到内存。

有什么建议吗?

+1

您是否尝试过使用fwrite()来逐行写入它? – Crashspeeder 2011-05-16 17:54:55

问题是,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); 
} 

这将限制数据试图在任何给定的时间在数据到处滥用的量。

+0

虽然本质上正确,但在原始中如何使用'echo $ content',因此它只是'$ content = // CSV格式; fwrite($ file,$ content);'并将'fopen'和'fclose'移出主循环。 – chx 2011-05-16 17:59:01

+0

你确定打开和关闭文件真的有必要吗?否则,我同意,尝试使用fwrite一次在线写入文件。 – 2011-05-16 18:00:10

+0

比赛条件任何人?如果第二个用户加载这个而另一个用户仍在等待它加载呢?我认为数据腐败是可能的,甚至可能是因为在办公室环境中,用户可能都会同时看到这样的事情。 – sakatc 2011-05-16 18:12:10

我完全同意一次写一行,你永远不会有这样的内存问题,因为一次不会有超过1行加载到内存中。我有一个相同的应用程序。然而,我用这种方法发现的一个问题是,该文件需要永久完成写作。所以这篇文章是为了支持已经说过的话,而且要求你们所有人就如何加速这个问题发表意见。例如,我的系统根据压缩文件清理数据文件,因此我一次只读一行,并在压缩文件中查找匹配项,然后如果找不到匹配项,则将该行写入新的已清理文件。然而,一个50k行文件需要大约4个小时才能完成,所以我希望找到一个更好的方法。我已经尝试了几种方法,现在我将整个压缩文件加载到内存中,以避免我的主循环必须通过压缩文件中的每一行运行另一个循环,但即使这样也需要花费数小时。

因此,逐行是迄今为止管理系统内存的最好方法,但我想要处理一个50k行文件(行是电子邮件地址和姓名)的处理时间以完成运行如果可能的话在不到30分钟内。如下所示:fill:压缩文件的大小为16,000 kb,由memory_get_usage()告知的脚本的总内存大小为35 megs。

谢谢!