【发布时间】:2012-05-25 15:05:59
【问题描述】:
我有一个表,其中包含大约 30 万行描述 Apple 推送通知服务的设备。我使用 Doctrine 2 作为 ORM。
插入设备没有问题,但是,检索它们是完全不同的故事。使用简单的 MySQL SELECT 我可以在几秒钟内获得它们,而 WiFi 是主要瓶颈。但是,如果我尝试通过 Doctrine 获取它们,即使我允许 PHP 高达 1 GB,它也会耗尽内存。根据文档,我已经为 Doctrine 实体创建了 getter 和 setter 以及受保护的属性。
我不知道我做错了什么。这很好:
$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);
}
【问题讨论】:
-
那是因为你在内存中创建了 300k 个实体实例。
-
每个实体实例消耗超过 4(四个!)MB 的内存?那么延迟加载有什么意义呢?在我看来,每个实例只有在您通过 getter 请求属性时才会被填充,就像 mysql 结果集一样。
-
我很确定它延迟加载实体,而不是将映射到实体的数据。所以在某个地方你有 300k 元素数组,每个元素都有至少一个属性(PK)。并且每次你做
$device->getPushToken时都会水合到一个物体上。除非您专门销毁该对象,否则它仍在内存中,因此即使我对细节不正确,延迟加载也不适用对象水合,特别是如果您只需要 2 个属性。 -
但即便如此,这可能会消耗大约 300 兆内存。我不希望这会用完千兆字节的内存。我真的很想知道如何和什么,如果我听起来脾气暴躁,很抱歉! :)
标签: php memory doctrine doctrine-orm