我已经遇到过这个问题了几次。
我有一段将数据导出到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。这在我的案例中不起作用。
我认为有一种方法可以对此查询进行分块并仍构建整个文件 - 任何人都可以推荐或指向我一个明确的教程吗?
答案 0 :(得分:1)
根据您要检索的元素数量(例如:getValue1
,getValue2
等),您可以保留结果in a different way:
$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
}
你可以检查的其他事情很少。关于memory leak form Propel的法语论文。
答案 1 :(得分:-1)
这是写入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);
}