我有可以执行的下一个代码,但是需要太多时间...有什么办法可以使我用createQueryBuilder和update方法来优化它?
这是当前功能:
private function getCsv()
{
$file = 'Diva_tarif.csv';
Message::write("Retriving $file", 3);
$file = $this->root_data . $file;
$serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder(';')]);
$counter = 0;
$batch_size = 30;
if (($handle = fopen($file, 'r')) !== false) {
$header = fgets($handle);
while (($line = fgets($handle)) !== false) {
$line = $serializer->decode($header . $line, 'csv');
$repo = $this->em->getRepository(Article::class);
if(isset($line['DOS'])){
$counter ++;
$arts = $repo->findBy(array('dos' => $line['DOS'], 'ref' => $line['REF']));
$used_metas = [
'TACOD',
'VENUN',
'DEV',
'PUB',
'ALZTXREMMAX',
'ALZTXREMMAXLALPHA',
];
foreach($arts as $art){
foreach ($used_metas as $metakey ) {
$meta_obj = new ArticleMeta();
$meta_obj->setName($metakey);
$meta_obj->setValue($line[$metakey]);
$meta_obj->setArticle($art);
$this->em->persist($meta_obj);
}
}
if (($counter % $batch_size) === 0) {
$this->em->flush();
$this->em->clear();
}
if(($counter % 500) == 0){
Message::write("$counter lines added", 4);
}
}
}
Message::write("$counter lines added", 4);
Message::write("Done", 3);
$this->em->flush();
$this->em->clear();
fclose($handle);
}
}
目的是获取Article并将新的值分配给ArticleMeta。
任何的想法?
最佳答案
您可以不使用序列化器而直接使用CsvEncoder
,而可以使用不进行非规范化的解码。
我区分两种提高绩效的方法
没有代码更改
您应该将一对ref-dos
索引到数据库中,这确实会增加查询时间。
但是执行脚本的时间会随着文件行数的增加而增加。
一个大查询
您可以解析一次文件,提取所有dos
和ref
,然后使用对ref-dos
构建一个数组。
示例:[ABCD-1234
,BCDE-2345
,...]
之后,您可以对数据库执行ONE
大查询,并且避免执行一个查询/一行,这是IMO非常耗时的。
这种方式与行数的关系较少,因为您只查询数据库一次。
这样,IMO是最好的
此外,您可以在while之外声明$used_metas
和$repo
。
您已经在使用批处理+实体管理器清理,这是在使用Doctrine插入许多实体时的一种好方法。
如果您真的想快一点,可以使用原始SQL并避免该学说实体水化。但是我不建议你这样
关于symfony - 从一个存储库到另一个存储库的Symfony大量 hydration ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52169209/