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

时间:2021-12-01 04:06:34

While using doctrine, I noticed that, to delete an entity, I need to retrieve that entity by given parameter(name,id etc) and then call the remove method. On the other hand, in query, I can just execute delete query.

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

So, seems like, using ORM style requires two operation and general sql operation require one operation. That's why, I am a little confusing, whether we should use delete(or update) operation in ORM? Isn't it worse in performance? Or Is there anything else I am missing? Can it be done in any other way in ORM style?

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

2 个解决方案

#1


38  

In Doctrine2 you can call the delete on a proxy object, which is not loaded from the database. Just create a "dummy" object, something like:

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

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

It doesn't require the initial query, but I'm not quite sure if Doctrine still does it internally on flush. I don't see it in the SqlLog.

它不需要初始查询,但我不太确定Doctrine是否仍在内部进行刷新。我在SqlLog中没有看到它。

Just to add, I think this is expected behavior of any decent ORM. It deals with objects and relations. It has to know that something exists before deleting it. ORM is not just a query generator. Generally, a native query will always be faster in any ORM. Any ORM adds a layer of abstraction and it takes some time to execute it. It is a typical tradeoff, you get some fancy features and clean code, but loose some on performance.

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

EDIT:

编辑:

I'm glad it worked out for you. Actually I stumbled on another problem, which made me realize that proxies and partial objects aren't actually the same thing. Partial objects instance the real model class, and fill it with values you want. After you initialize a partial object lazy-loading doesn't work on it anymore. So for instance, if you make a partial object with only the id, and want to delete only if another object field satisfies some condition, it will not work, because that other field will always be null.

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

On the other hand, proxies do work with lazy-loading, and don't share the problems that partial objects have. So I would strongly suggest not to use getPartialReference method, instead you can do something like:

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

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

The getReference method returns the object if it is already loaded or a proxy if it is not. A proxy can lazy-load all the other values if/when you need them. As for your example, they will behave exactly the same, but proxies are surely a better way to go.

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

#2


4  

Done! for me it worked like this add line 3:

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

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

#1


38  

In Doctrine2 you can call the delete on a proxy object, which is not loaded from the database. Just create a "dummy" object, something like:

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

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

It doesn't require the initial query, but I'm not quite sure if Doctrine still does it internally on flush. I don't see it in the SqlLog.

它不需要初始查询,但我不太确定Doctrine是否仍在内部进行刷新。我在SqlLog中没有看到它。

Just to add, I think this is expected behavior of any decent ORM. It deals with objects and relations. It has to know that something exists before deleting it. ORM is not just a query generator. Generally, a native query will always be faster in any ORM. Any ORM adds a layer of abstraction and it takes some time to execute it. It is a typical tradeoff, you get some fancy features and clean code, but loose some on performance.

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

EDIT:

编辑:

I'm glad it worked out for you. Actually I stumbled on another problem, which made me realize that proxies and partial objects aren't actually the same thing. Partial objects instance the real model class, and fill it with values you want. After you initialize a partial object lazy-loading doesn't work on it anymore. So for instance, if you make a partial object with only the id, and want to delete only if another object field satisfies some condition, it will not work, because that other field will always be null.

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

On the other hand, proxies do work with lazy-loading, and don't share the problems that partial objects have. So I would strongly suggest not to use getPartialReference method, instead you can do something like:

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

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

The getReference method returns the object if it is already loaded or a proxy if it is not. A proxy can lazy-load all the other values if/when you need them. As for your example, they will behave exactly the same, but proxies are surely a better way to go.

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

#2


4  

Done! for me it worked like this add line 3:

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

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