Ich habe einen symfony-Befehl erstellt, der 2M-Einträge importieren und in die Datenbank einfügen soll.Symfony3/Doctrine 2 flush error
Ich lege einen Flush/Clear und gebe alle 500 Einträge, um es mit Doktrin einfügen und den Fortschritt der Insertion verfolgen zu können. Auf meinem Rechner mit einem Server mySQL Datenbank es funktioniert, aber auf dem entfernten Server mit Postgresql funktioniert es nicht, bekomme ich eine Nachricht:
[Symfony\Component\Debug\Exception\ContextErrorException]
Notice: Undefined index: 0000000025969b1e00000000029e7855
Exception trace:
() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:2917
Doctrine\ORM\UnitOfWork->getEntityIdentifier() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php:656
Doctrine\ORM\Persisters\Entity\BasicEntityPersister->prepareUpdateData() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php:692
Doctrine\ORM\Persisters\Entity\BasicEntityPersister->prepareInsertData() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php:271
Doctrine\ORM\Persisters\Entity\BasicEntityPersister->executeInserts() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1014
Doctrine\ORM\UnitOfWork->executeInserts() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:378
Doctrine\ORM\UnitOfWork->commit() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:356
Doctrine\ORM\EntityManager->flush() at /var/nginx/kweeri-next/var/cache/dev/appDevDebugProjectContainer.php:6083
DoctrineORMEntityManager_00000000612352fa000000006464aa610448bf5c446411a05ad87329e18cead6->flush() at /var/nginx/kweeri-next/src/AppBundle/Utility/Clients/IRI/PPS/ImportItems.php:219
Dies ist der Code, wo der Flush eine Mitteilung stellt.
public function importDictionnary($companyMachineName, $file) {
$company = $this->em->getRepository("AGAdminBundle:Company")->findOneBy(["machineName" => $companyMachineName]);
if (!$company) {
throw new EntityNotFoundException("no company found for $companyMachineName");
}
$eans = $file;
$this->logger->addInfo("File downloaded");
$product_repo = $this->em->getRepository(\AppBundle\Entity\PPS\Product::class);
$existings = array_map(function (\AppBundle\Entity\PPS\Product $product) {
return $product->getEan();
}, $product_repo->findBy(["company" => $company]));
$old_value = -1;
foreach ($eans as $k => $ean) {
if (!in_array($ean, $existings)) {
$this->em->persist(new \AppBundle\Entity\PPS\Product($ean, $company));
if ($k % 500 == 0) {
yield round(($k/count($eans)) * 100);
$this->em->flush();
$this->em->clear();
}
}
}
$this->em->flush();
}
EDIT: es arround 30 Sekunden dauert 2 auf meinem Rechner zu erhalten. Auf der entfernten Maschine dauert es bis zu 20 Minuten, bevor sie 2 ergibt und stoppt.
Nicht so vertraut mit der Ausbeute, wie ich sein sollte. Wird $ company nach jeweils 500 Loops neu geladen? Wenn nicht, dann sollte die mysql-Version natürlich ebenfalls fehlschlagen. – Cerad
@Cerad Ich habe dieses Problem behoben, indem ich die CompanyId beibehalten und dann nur die Referenz neu laden konnte, wie in einer Antwort vorgeschlagen. aber immer noch sehr langsam: 2 Stunden auf mySQL, 11 Stunden auf PostgreSQL. – d3cima
Es gibt einige hundert Fragen zur Beschleunigung von Importen. Aber keine magische Kugel. Die Verwendung des ORM fügt einen nicht-trivialen Overhead hinzu. Wenn man auf DBAL herunterfährt, hilft das sehr, aber 1,5 Millionen von allem zu tun, wird langsam sein, egal was passiert. – Cerad