2010-07-02 72 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