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 に答える