2

Appleのプッシュ通知サービス用のデバイスを説明する約30万行を含むテーブルがあります。私はDoctrine2をORMとして使用しています。

デバイスの挿入は問題ありませんが、デバイスの取得はまったく別の話です。単純なMySQLSELECTを使用すると、WiFiが主なボトルネックである数秒でそれらを取得できます。ただし、Doctrineを介してそれらをフェッチしようとすると、最大1ギガバイトのPHPを許可しても、メモリが不足します。ドキュメントに従って、Doctrineエンティティのゲッターとセッターおよび保護されたプロパティを作成しました。

何が間違っているのかわかりません。これは問題ありません:

$devices = mysql_query("SELECT * FROM `Devices` WHERE `deviceProperty`='someValue'");

$message = new Message();
while($device = mysql_fetch_array($devices))
{
    $message->addRecipient($device['pushToken']);
}

ただし、これは最初の行のメモリが不足します(次の行のブレークポイントに到達することはありません)。

$devices = self::$entityManager->getRepository('Device')->findBy(array("deviceProperty" => "someValue"));
$message = new Message();
foreach($devices as $device)
{
    $message->addRecipient($device->getPushToken);
}
4

2 に答える 2

3

300kのオブジェクトをプルしているので、メモリを大量に消費します。チャンクで処理してみてください...

$message = new Message();

$limit = 50;
$offset = 0;
while($devices = self::$entityManager->getRepository('Device')->findBy(array("deviceProperty" => "someValue"), array(), $limit, $offset))
{
   foreach($devices as $device)
   {
       $message->addRecipient($device->getPushToken);
   }
   $offset += $limit;
}
于 2012-05-25T16:18:20.030 に答える
0

DQLを使用している場合は、iterate()関数を使用して結果を反復処理し、処理後に各結果をフラッシュできます。

$message = new Message();
$cleaner = 0;

$q = self::$entityManager->createQuery(
    'SELECT d from Device d
     WHERE
     d.deviceProperty = :devicePropertyValue
    ');
$q->setParameter('devicePropertyValue', 'someValue');
//$q->setFirstResult(10000);
//$q->setMaxResults(5000);

$devices = $q->iterate();

foreach ($devices as $row) {
    $device = $row[0];

    $message->addRecipient($device->getPushToken);

    self::$entityManager->detach($device);

    if ($cleaner++ > 100) {
        self::$entityManager->clear();
        $cleaner = 0;
    }

}

私が実行しているバッチ再インデックスジョブの場合、これによりメモリ要件が3GBから256M未満に減少しました。

Doctrineのドキュメントによると、「コレクションと値の関連付けをフェッチして結合するクエリでは、結果を反復処理することはできません」-これは、findBy()などの組み込みメソッドを意味すると思います。

オフセットと制限に使用できるコメントアウトされたsetFirstResult()とsetMaxResults()に注意してください。

于 2015-01-22T10:18:46.213 に答える