2010-07-02 55 views
1

我已经编写了一个用于PHP中数据库复制的工具。它工作正常,但有一个问题:使用PDO获取大型结果集时保存内存

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

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

,它遍历结果在while循环设定PDOStatement::fetch();后,做一些类型转换和逃避,构建一个INSERT声明和供稿到目标数据库。

所有这些都很好地工作,只有一个例外。在从结果集中取一行时,PHP进程不断占用越来越多的内存。我的想法是,PDO将已处理的行保留在内存中,直到处理完整个结果集为止。

我还看到,当我的工具完成一张表并进入下一个时,内存消耗会立即下降,这支持了我的理论。

我不保留数据在PHP变量!我在任何特定时刻只保留一行进行处理,所以这不是问题。

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

回答

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 
+0

也许这可以帮助,但是这只是太DBMS具体。该工具必须适用于多个数据库系统,任何非通用解决方案都太容易出错。我也认为将查询划分为多个请求会降低整体性能。 – selfawaresoup 2010-07-02 11:28:55

+0

也许使用[Zend_Db_Select](http://framework.zend.com/manual/en/zend.db.select.html)并生成与数据库无关的查询 – clyfe 2010-07-02 11:37:29