Doctrine实体删除vs删除查询,性能比较

时间:2012-07-14 19:15:55

标签: php performance doctrine

在使用doctrine时,我注意到,要删除实体,我需要通过给定的参数(name,id等)检索该实体,然后调用remove方法。另一方面,在查询中,我只能执行删除查询。

所以,好像,使用ORM样式需要两个操作并且一般的sql操作需要一个操作。这就是为什么我有点困惑,我们是否应该在ORM中使用删除(或更新)操作?表现不是更差吗?或者还有什么我想念的吗?可以用ORM风格的任何其他方式完成吗?

2 个答案:

答案 0 :(得分:38)

在Doctrine2中,您可以在代理对象上调用delete,该代理对象不是从数据库加载的。只需创建一个“虚拟”对象,如:

$user = $em->getPartialReference('model\User', array('id' => $id));
$em->remove($user);

它不需要初始查询,但我不太确定Doctrine是否仍在 flush 内部执行此操作。我没有在SqlLog中看到它。

只是补充一下,我认为这是任何体面的ORM的预期行为。它涉及对象和关系。在删除它之前必须知道存在某些东西。 ORM不仅仅是查询生成器。通常,任何ORM中的本机查询总是更快。任何ORM都会添加一个抽象层,执行它需要一些时间。这是一个典型的权衡,你得到一些花哨的功能和干净的代码,但在性能上有所松动。

修改

我很高兴为你效劳。实际上我偶然发现了另一个问题,这让我意识到代理和部分对象实际上并不是同一个东西。部分对象实例化实际模型类,并用您想要的值填充它。初始化部分对象后,延迟加载不再适用于它。因此,例如,如果您创建仅具有id的部分对象,并且仅在另一个对象字段满足某些条件时才想删除,则它将不起作用,因为其他字段将始终为null。

另一方面,代理确实可以使用延迟加载,并且不会共享部分对象所具有的问题。所以我强烈建议不要使用getPartialReference方法,而是可以执行以下操作:

$user = $em->getReference('model\User', $id);
$em->remove($user);

getReference方法返回已加载的对象,如果不加载则返回代理。如果/当您需要时,代理可以延迟加载所有其他值。至于你的例子,它们的行为完全相同,但代理肯定是更好的方法。

答案 1 :(得分:4)

完成! 对我来说,它就像这个添加第3行:

$user = $em->getReference('model\User', $id);
$em->remove($user);
$em->flush();