3

我们遇到了一个奇怪的问题。它是这样的。我们有大量数据需要输出给客户。这些数据文件不能预先构建,它们必须从实时数据中提供。

我首选的解决方案是从这样的提取中逐行写入 CSV:

 while($datum = $data->fetch(PDO::FETCH_ASSOC)) {
            $size += fputcsv($outstream, $datum, chr(9), chr(0));
 }

这解决了很多荒谬的内存使用(一次将 100000 条记录读入内存是不好的魔力),但是对于大型表,我们仍然存在挥之不去的问题,随着数据大小的增加,这些问题只会变得更糟。请注意,没有数据分区;他们不按年份分段下载,而是下载所有数据,然后自行分段。这是按照要求;我无法改变这一点,因为它会完全消除问题。

在任何一种情况下,在最大的表上都会耗尽内存。一种解决方案是增加可用内存,这解决了一个问题,但如果有多个客户端正在下载,则建议稍后甚至现在创建服务器负载问题。

在这种情况下,$outstream 是:

$outstream = fopen("php://output",'w');

这似乎很明显不是一个物理磁盘位置。在将数据发送到客户端之前,我不太了解 php://output 数据所在的位置,但很明显,通过这种方法将多个数据库表简单地写入 csv 存在内存问题。

准确地说,暂存盒允许 PHP 使用大约 128mb,特别是这个调用短了大约 40mb(它试图多分配 40mb。)这对于行为来说似乎有点奇怪,因为你会期望它请求更小的内存部分。

任何人都知道可以做些什么来处理这个问题?

4

1 回答 1

2

所以看起来内存消耗是由 Zend Framework 的输出缓冲引起的。我想出的最好的解决方案就是这个。

在我们开始将文件流式传输到客户端之前执行 ob_end_clean() 。ZF 的这个特殊实例在此之后不会产生任何正常输出或做任何其他事情,因此不会出现并发症。确实发生了奇怪的事情(也许从用户的角度来看)是他们确实将文件流式传输给了他们。

这是代码:

ob_end_clean();
while($datum = $data->fetch(PDO::FETCH_ASSOC)) {
            $size += fputcsv($outstream, $datum, chr(9), chr(0));
}

内存使用量(根据某处 ZF 论坛帖子中建议的函数 memory_get_peak_usage(true))从 90 兆字节下降到 9 兆字节,这是在读取任何文件之前在我的开发盒上使用的内存。

谢谢你们的帮助,伙计们!

于 2012-06-27T15:10:24.447 回答