доктрина 2.1: использование памяти увеличилось после сброса
Мне действительно непонятно, почему после flush() память увеличивается, а не уменьшается? Я не могу найти ничего полезного в документации. Я промываю каждые 50 итераций цикла, и после каждой промывки использование памяти увеличивается на 1 МБ. При 100 промывках используется 100 МБ! Что я здесь упускаю? Я видел на веб-сайте doctrine пример с clear(), но если я его использую, я получаю исключение, что у одного из моих объектов нет набора каскадного сохранения. Может ли кто-нибудь объяснить мне, что такое сделано за кулисами, и что я должен сделать, чтобы правильно отменить все объекты доктрины?
3 answers
Проблема в том, что менеджер сущностей обрабатывает все объекты. Вы должны сбросить его, если вам не нужны объекты в оперативной памяти после каждой X итераций. Попробуйте это:
// get the entity manager and save objects and flush
$em = $this->get('doctrine')->getEntityManager();
...
$em->flush();
// then reset the entity manager
$this->get('doctrine')->resetEntityManager();
Также читайте здесь: http://docs.doctrine-project.org/en/2.0.x/reference/batch-processing.html
Он предлагает использовать $em->clear() после каждого объема операций. (что должно дать тот же эффект, что и предложил Бесник).
По ранее упомянутой ссылке:
Массовые вставки в доктрине лучше всего выполнять пакетами, используя преимущества транзакционного поведения EntityManager при записи. В следующем коде показан пример для вставка 10000 объекты с размером пакета 20. Возможно, вам придется поэкспериментировать с размером пакета, чтобы найти наиболее подходящий для вас размер. Большая партия размеры означают более подготовленное повторное использование инструкции внутри, но также означают больше работы во время промывки.
У меня была аналогичная ситуация с массовой вставкой записей (более 100 тыс.). Я следовал советам Рауни и Бесника и руководству Доктрины по пакетной обработке, но память все равно росла даже после $em->очистить() и resetEntityManager(). Через несколько дней я возглавил информационное уведомление о документации Доктрины:
Инструмент ORM в первую очередь не подходит для массовых вставок, обновлений или удалений. Каждая СУБД имеет свой собственный, наиболее эффективный способ решения таких операций, и если вариантов, описанных ниже, недостаточно для ваших целей. мы рекомендуем вам использовать инструменты для вашего конкретного СУБД для этих массовых операций.
И использовал необработанный SQL (MySQL) и пакетировал вставки. Использование памяти увеличилось с более чем 200 МБ с помощью Doctrine до 30 МБ с необработанным SQL. И я мог видеть, как уменьшается использование памяти, когда я извлекал элементы для вставки из исходного массива. Также намного быстрее, с 220 секунд до 20 секунд.