大的Excel导入到DB在Symfony中变得非常缓慢

我有一个脚本,导入大量的foreach es的大型Excel文件,经过50次迭代,速度变得难以忍受…我可以改进这个吗?

我试图尽可能使它可读:

 foreach worksheet (approx 20) { NEW DB ENTRY, PERSIST, FLUSH (account) foreach row (10-100){ NEW DB ENTRY, PERSIST, FLUSH (object) foreach column (approx. 10){ CREATE NEW DB ENTRY, FOREIGN KEY to 'object', PERSIST, FLUSH (weekdates) } foreach column (approx. 50){ CREATE NEW DB ENTRY, FOREIGN KEY to 'object', PERSIST, FLUSH (scheduleEntry) CREATE NEW DB ENTRY, FOREIGN KEY to 'scheduleEntry', PERSIST, FLUSH (scheduleObject) CREATE NEW DB ENTRY, FOREIGN KEY to 'scheduleObject', PERSIST, FLUSH (scheduleModule) /* WORST CASE IS THAT HERE WE HAVE FLUSHED 100000 times */ } } } 

有没有一种方法来加强特别是最后一个foreach? 我想我需要刷新每一次,因为我必须将外键input到新键盘上,对吗? 慢,我的意思是Excel文件需要24小时以上导入。 它在这个例子中有数字。

实际的(仍然是简单的)代码看起来像这样

 /* Create Excel */ $excel = $this->getContainer()->get('phpexcel')->createPHPExcelObject(Constants::FULL_PATH . 'excel/touren_' . $filename . '.xls'); $sheets = $excel->getAllSheets(); foreach ($sheets as $id => $sheet) { $ws = $sheet->toArray(); /* Read sth from first line and create an 'account' from this */ $n = new Network(); .... $em->persist($n); try { $em->flush(); $output->writeln('----><info>Inserted in DB</info>'); } catch (Exception $e) { $output->writeln('----><error>DB ERROR</error>'); } /* Go through all rows of current WorkSheet */ foreach ($ws as $row) { /* Create new Object */ $object = new Object(); ... $em->persist($object); try { $em->flush(); $output->writeln("------->Save Object to DB: <info>OK</info>"); } catch (\Exception $e) { $output->writeln("------->Save Object to DB: <error>Failed: " . $e->getMessage() . "</error>"); } /* Create new Tour for weekday/client */ $tour = new Tour(); $tour->setNetwork($n); /* More foreach */ foreach ($clientKey as $filialNo => $filialKey) { $tourObject = new TourObject(); $tourObject->setTour($tour); $tourObject->setObject($o); $em->persist($tourObject); /* Count Intervals */ foreach ($filialKey as $tasks) { if (!$tourObject->getModule()->contains($module)) { $tourObject->addModule($module); $em->persist($tourObject); /* More foreach */ foreach ($period as $date) { $schedule = new Schedule(); $schedule->setTour($tour); .... $em->persist($schedule); try { $em->flush(); $output->writeln("------->Save Schedule to DB: <info>OK</info>"); } catch (\Exception $e) { $output->writeln("------->Save Schedule to DB: <error>Failed: " . $e->getMessage() . "</error>"); } $scheduleObject = new ScheduleObject(); $scheduleObject->setSchedule($schedule); .... $em->persist($scheduleObject); try { $em->flush(); $output->writeln("------->Save ScheduleObject to DB: <info>OK</info>"); } catch (\Exception $e) { $output->writeln("------->Save ScheduleObject to DB: <error>Failed: " . $e->getMessage() . "</error>"); } $scheduleObjectModule = new ScheduleObjectModule(); $scheduleObjectModule->setScheduleObject($scheduleObject); $em->persist($scheduleObjectModule); try { $em->flush(); $output->writeln("------->Save ScheduleObjectModule to DB: <info>OK</info>"); } catch (\Exception $e) { $output->writeln("------->Save ScheduleObjectModule to DB: <error>Failed: " . $e->getMessage() . "</error>"); } } } } } /* Flush all?!? */ try { $em->flush(); $output->writeln("------->Save Task to DB: <info>OK</info>"); } catch (\Exception $e) { $output->writeln("------->Save Task to DB: <error>Failed: " . $e->getMessage() . "</error>"); } } 

您通过EntityManager创build/保存的每个实体都存储在UnitOfWork中,现在成为一个“托pipe”实体。 如果这个UnitOfWork填满了,它在系统上相当沉重。 你可以在每个“sheet”之后调用$ entityManager-> clear(),这样每次迭代之后UoW都会被清除。

每个实体都有自己的UnitOfWork,你可以单独清除每个实体的UoW,但是由于你创build了很多的实体,我build议不要指定一个实体类,只是清除所有的实体。

  ... /* Flush all?!? */ try { $em->flush(); $em->clear(); $output->writeln("------->Save Task to DB: <info>OK</info>"); } catch (\Exception $e) { $output->writeln("------->Save Task to DB: <error>Failed: " . $e->getMessage() . "</error>"); } 

或者你可以使用本地查询来插入你的数据库,但是这可能并不总是你想要的数据一致性等。

同样如上所述,在每个实体之后不需要刷新。 如果你只调用一次flush,在每个'sheet'之后,Doctrine会立即执行所有的insert语句。

我认为一个好的解决scheme是使用本地数据库实用程序(例如Mysql Load data infile )

这要比使用PHP编写的任何东西都要快得多。

Interesting Posts