我有下一个代码执行正常,但它需要太多时间...有没有办法我可以用createQueryBuilder和更新方法来优化这个?
这是当前的功能:
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);
}
}
目标是获取文章并为ArticleMeta分配新值。任何的想法?
您可以在没有Serializer的情况下直接使用CsvEncoder
,您正在使用没有非规范化的解码。
我区分了两种提高表现的方法
您应该将对ref-dos
索引到您的数据库中,这将真正增加查询时间。
但是执行脚本的时间会随着文件的行数而增加。
您可以解析一次您的文件,提取所有dos
和ref
,然后使用对ref-dos
构建一个数组。
示例:[ABCD-1234
,BCDE-2345
,...]
之后,您可以对您的数据库执行ONE
大查询,并避免一个查询/行,IMO非常耗时。
这种方式与行数的关系较少,因为您只查询一次数据库。
这样IMO是最好的
此外,你可以在外面声明$used_metas
和$repo
。
您已经在使用批处理+实体管理器清理,这是使用Doctrine插入许多实体时的好方法。
如果你真的想要快速,你可以使用原始SQL并避免学说实体的水合作用。但我不建议你这样做