Doctrine entity remove vs delete query, сравнение производительности

При использовании доктрины я заметил, что для удаления объекта мне нужно получить этот объект по заданному параметру (имя, идентификатор и т.д.), а затем вызвать метод удаления. С другой стороны, в запросе я могу просто выполнить запрос на удаление.

Итак, похоже, что с использованием стиля ORM требуется две операции, а общая операция sql требует одной операции. Поэтому я немного запутался, следует ли нам использовать операцию удаления (или обновления) в ORM? Разве это не хуже в производительности? Или есть что-то еще, что мне не хватает? Можно ли это сделать другим способом в стиле ORM?

Ответы

Ответ 1

В Doctrine2 вы можете вызвать delete на прокси-объекте, который не загружен из базы данных. Просто создайте объект "dummy", например:

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

Он не требует начального запроса, но я не совсем уверен, что Doctrine все еще делает это внутренне на fush. Я не вижу его в SqlLog.

Просто чтобы добавить, я думаю, что это ожидаемое поведение любого приличного ORM. Он касается объектов и отношений. Он должен знать, что перед удалением чего-то существует. ORM - это не просто генератор запросов. Как правило, собственный запрос всегда будет быстрее в любом ORM. Любая ORM добавляет слой абстракции, и для ее выполнения требуется некоторое время. Это типичный компромисс, вы получаете некоторые причудливые функции и чистый код, но немного теряете производительность.

EDIT:

Я рад, что это сработало для вас. Фактически я наткнулся на другую проблему, которая заставила меня понять, что прокси и частичные объекты на самом деле не то же самое. Частичные объекты представляют экземпляр реального класса модели и заполняют его необходимыми значениями. После инициализации частичного объекта lazy-load больше не работает на нем. Например, если вы делаете частичный объект только с идентификатором и хотите удалить только в том случае, если другое поле объекта удовлетворяет некоторому условию, оно не будет работать, потому что это другое поле всегда будет нулевым.

С другой стороны, прокси-серверы работают с ленивой загрузкой и не разделяют проблем, которые имеют частичные объекты. Поэтому я настоятельно рекомендую не использовать метод getPartialReference, вместо этого вы можете сделать что-то вроде:

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

Метод getReference возвращает объект, если он уже загружен, или прокси-сервер, если это не так. Прокси-сервер может ленить все остальные значения, если/когда они вам понадобятся. Что касается вашего примера, они будут вести себя точно так же, но прокси-серверы, безусловно, лучший способ пойти.

Ответ 2

Готово! для меня это сработало, как это добавить строку 3:

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