使用PDO获取大型结果集时节省内存

时间:2010-07-02 11:10:28

标签: php optimization memory pdo resultset

我在PHP中编写了一个用于数据库复制的工具。它工作正常,但有一个问题:

我正在使用PDO连接到不同的数据库,以使其独立于任何特定的RDBMS,这对此应用程序至关重要。

该工具对表进行一些分析,以决定如何转换某些类型和其他一些东西。然后它几乎用“SELECT * FROM <tablename>”来获取需要复制的行。结果集相当大(某些表中大约有50k行)。

之后,它使用whilePDOStatement::fetch();循环中迭代结果集,执行某些类型转换和转义,构建INSERT语句并将其提供给目标数据库。 / p>

所有这一切都很好地解决了一个例外。在从结果集中获取行时,PHP进程一直在占用越来越多的内存。我的结论是,PDO将已处理的行保留在内存中,直到处理完整个结果集。

我还注意到,当我的工具完成一个表并继续下一个表时,内存消耗会立即下降,这支持了我的理论。

我没有将数据保存在PHP变量中!我在任何给定时刻只持有一行进行处理,所以这不是问题。

现在提出一个问题:是否有办法强制PDO不要将所有数据保存在内存中?我一次只处理一行,所以绝对没有必要保留所有垃圾。我真的很想在这件事上少用内存。

1 个答案:

答案 0 :(得分:2)

我认为问题来自php的垃圾收集器,因为它不会很快收集垃圾 我会尝试以row_count大小的块来获取结果,例如MySQL中的"SELCT ... LIMIT offset, row_count"或ORACLE中的"SELECT * FROM (SELECT ...) WHERE ROW_NUM BETWEEN offset AND (offset + row_count)"
使用Zend_Db_Select可以生成与DB无关的查询:

$select = $db->select()
    ->from(array('t' => 'table_name'),
        array('column_1', 'column_2'))
    ->limit($row_count, $offset);
$select->__toString(); 
# on MySQL renders: SELECT column_1, column_2 FROM table_name AS t LIMIT 10, 20