2

在执行这个简单的代码(对于 MySQL 数据库)后,每次循环迭代我会减少 1kB 的内存,所以在第 1000 次迭代后,我使用了大约 1MB 的内存。

现在,如果我必须循环运行一个长时间运行的脚本(大约 1 000 000 次迭代),我很快就会内存不足

$_db = Zend_Db_Table::getDefaultAdapter();

$start_memory = memory_get_usage();

for ($i=0; $i<1000; $i++) {
    $update_query = "UPDATE table SET field='value'";
    $_db->query($update_query);
}

echo 'memory used: '.(memory_get_usage()-$start_memory);

有没有办法释放数据库查询使用的内存?

我试图将更新查询放在一个函数中,因此在离开函数范围后,该函数使用的资源应该被自动释放:

function update($_db) {
  $sql = "UPDATE table SET field='value'";
  $_db->query($sql);
}
...
for ($i=0; $i<1000; $i++) {
    update($_db);
}

但他们不是!

我对“尝试一次更新多行”之类的建议不感兴趣;)

4

2 回答 2

6

很可能您启用了Zend_Db_Profiler 。

数据库分析器存储每个执行的查询,这对于调试和优化非常有用,但如果您执行大量查询,则会导致相当快的内存耗尽。

在您给出的示例中,禁用分析器应该可以解决问题:

$_db = Zend_Db_Table::getDefaultAdapter();
$_db->getProfiler()->setEnabled(false);

$start_memory = memory_get_usage();

for ($i=0; $i<1000; $i++) {
    $update_query = "UPDATE table SET field='value'";
    $_db->query($update_query);
}

echo 'memory used: '.(memory_get_usage()-$start_memory);
于 2012-06-01T12:42:32.023 回答
0

当多次执行相同的查询时,节省内存的最佳方法是实现预准备语句。您的适配器将使用准备好的语句,但由于您在循环内调用 query() 方法,因此每次都准备好。将其移出循环:

$_db = Zend_Db_Table::getDefaultAdapter();
$_stm = $_db->prepare("UPDATE table SET field='?'");

for ($i=0; $i<1000; $i++) {
    $_stm->execute(array($fieldValue));
} 
于 2012-06-01T12:44:51.057 回答