Мне нужно обновить сущности Doctrine, чтобы соответствовать записям внутри файла (potentionaly very large) XML. Я также должен обновлять ассоциации ManyToMany в соответствии с данными в XML. Это то, что я делаю внутри цикла:
- получить данные из XML
- получить сущность из БД (если не существует, создать новый)
- установить новые свойства объекта
- получить текущие ассоциации сущностей (getter возвращает
ArrayCollection
объект) - очистить все ассоциации (вызывая
ArrayCollection::clear()
) - установить новые ассоциации (вызывая
ArrayCollection::add()
в подцикле) - сохранить объект EntityManager
После цикла я вызываю EntityManager::flush()
.
Проблема заключается в том, что очистка генерирует большое количество запросов вместо обновления/вставки/удаления нескольких строк одновременно. Для каждого объекта выполняются следующие запросы:
- SELECT для получения сущности из базы данных
- UPDATE для обновления свойств объекта (это фактически пропущено сейчас, поскольку свойства не изменены... еще)
- УДАЛИТЬ, чтобы очистить предыдущие ассоциации.
- INSERT для вставки новых ассоциаций
Итак, в общей сложности для 305 записей в XML я получаю 915 запросов (я думаю, он мог бы доходить до 1220 запросов, если бы все сущности были изменены), что делает импорт очень медленным.
Я мог бы использовать IdentityMap и предварительную выборку сущностей до цикла, но все еще есть запросы UPDATE/DELETE/INSERT.
- Есть ли способ, чтобы метод flush лучше оптимизировал запросы (используйте multi-insert, WHERE IN вместо нескольких запросов DELETE и т.д.)?
- Это обычное поведение метода flush или я делаю что-то неправильно?
- Возможно, есть проблема в том, как я обновляю ассоциации сущности. Есть ли лучший способ, как это сделать? (вместо метода get/clear/add)
- Я знаю, что Doctrine не предназначен для массовой обработки betch, но я думаю, что использование этого для импорта XML - лучший способ избежать несоответствий БД, которые могут появиться с использованием подхода без ORM. Это правильно?
- Если описанный выше подход неверен, как мне решить проблему?