我遇到过几次这个问题。
我有一段将数据导出到 CSV 的代码。 我使用的方法将结果集传递给模板,模板循环浏览结果,回显字段。
在操作中:
$this->result = ObjectPeer::doSelect($criteria);
在模板中:
foreach ($result as $row)
{
echo $row->getValue1().','.$row->getValue2().','.$row->getValue3()...
}
但是,如果结果集很大,我将耗尽内存:
[error] PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 1556481 bytes) in exportSuccess.php on line 13, referer: https://mysite.com/module
该进程使用超过 250 mb,但它创建的文件只有 ~2 mb。我可以增加 php.ini 为该过程提供的内存量,但我宁愿不这样做。 如果导出足够大,我有点怀疑我是否能够给它足够的内存。
我读过其他一些类似的案例,建议在每次回声后取消设置$row。 这在我的情况下不起作用。
我认为有一种方法可以对此查询进行分块并仍然构建整个文件 - 任何人都可以推荐或指出我一个清晰的教程吗?
根据要检索的元素数量(即:getValue1
、getValue2
等),您可以通过不同的方式对结果进行水化处理:
$stmt = ObjectPeer::doSelectStmt($m_criteria);
while ($row = $stmt->fetch(PDO::FETCH_NUM))
{
echo $row[0];
}
此外,您可以使用doSelectRS
检查另一个解决方案:
$rs = ObjectPeer::doSelectRS($criteria);
$rs->setFetchMode(ResultSet::FETCHMODE_ASSOC);
while($rs->next())
{
$records = $rs->getRow();
// then use $records['key'] to retrieve information
}
您可以检查的其他一些事情。这个关于记忆泄漏的法国人形成了普罗佩尔。
这是写入 csv 文件的基本思想。 这不会显示与数据库的连接,但它是之后的所有内容,并确保在最后关闭连接。
$filename = 'c:'whatever.csv';
$fp = fopen($filename, "w") or die(mysql_error());
echo "Connected to ".$filename." <br>";
$res = mysql_query("SELECT *
FROM $table1
WHERE Something
");
// fetch a row and write the column names out to the file
echo mysql_error();
$row = mysql_fetch_assoc($res);
$line = "";
$comma = "";
foreach($row as $name => $value) {
$line .= $comma . '"' . str_replace('"', '""', $name) . '"';
$comma = ",";
}
$line .= "'n";
fputs($fp, $line);
// remove the result pointer back to the start
mysql_data_seek($res, 0);
// and loop through the actual data
echo mysql_error();
while($row = mysql_fetch_assoc($res)) {
$line = "";
$comma = "";
foreach($row as $value) {
$line .= $comma . '"' . str_replace('"', '""', $value) . '"';
$comma = ",";
}
$line .= "'n";
fputs($fp, $line);
}