Мне нужно импортировать большие данные из CSV-файла (около 1 млн записей).
Во избежание утечек памяти я пробовал массовую вставку из документации доктрины:
$batchSize = 20;
for ($i = 1; $i <= 10000; ++$i) {
//code
$em->persist($user);
if (($i % $batchSize) === 0) {
$em->flush();
$em->clear(); // Detaches all objects from Doctrine!
}
}
$em->flush(); //Persist objects that did not make up an entire batch
$em->clear();
Проблема в том, что моя вставка содержит отношения «многие к одному», и каждый раз, когда я использую clear (), объект дублирует записи из этого отношения.
Есть ли возможность отсоединить сущность и избежать дубликатов?
Да, есть. Вам нужно выполнить умную чистку. Это означает, что вы предоставляете тип сущности, который хотите очистить. Пример :
$em->clear(SomeEntity::class);
$em->clear(OtherEntity::class);
это удалит из EM только те типы и оставит все остальное. Таким образом, вы можете повторно использовать эти другие объекты.
Использование ORM для импорта больших данных занимает довольно много времени и памяти. Я никогда не нахожу способ сделать быстрый и вменяемый импорт с Doctrine. Помимо импорта, который я сделал таким образом, есть PITA для поддержки.
После многих лет импорта данных самый эффективный способ, который я нашел, это:
Таким образом, я могу импортировать дюжину больших CSV-файлов за считанные секунды.
Надеюсь, это поможет.