symfony - 从一个存储库到另一个存储库的Symfony大量 hydration

标签 symfony doctrine hydration

我有可以执行的下一个代码,但是需要太多时间...有什么办法可以使我用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索引到数据库中,这确实会增加查询时间。

但是执行脚本的时间会随着文件行数的增加而增加。

一个大查询

您可以解析一次文件,提取所有dosref,然后使用对ref-dos构建一个数组。

示例:[ABCD-1234BCDE-2345,...]

之后,您可以对数据库执行ONE大查询,并且避免执行一个查询/一行,这是IMO非常耗时的。

这种方式与行数的关系较少,因为您只查询数据库一次。

这样,IMO是最好的

此外,您可以在while之外声明$used_metas$repo

您已经在使用批处理+实体管理器清理,这是在使用Doctrine插入许多实体时的一种好方法。

如果您真的想快一点,可以使用原始SQL并避免该学说实体水化。但是我不建议你这样

关于symfony - 从一个存储库到另一个存储库的Symfony大量 hydration ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52169209/

相关文章:

php - Symfony2 DateTime 无法转换为字符串

php - 使用 Doctrine 和 Symfony 导出到 csv 文件

python - 为什么我不能使用TWARC/Hydrator 应用程序对24000个推文ID中的18个以上的推文进行补水?有谁知道更好的方法吗?

symfony - 带连接的 Doctrine querybuilder - hydrate 数组

arrays - 如何从具有ID的数组中创建模型的集合-Laravel

forms - Symfony2 : get post data from PRE_SET_DATA event

file - Symfony2 简单文件上传编辑,无实体

Symfony - 如何以 "many-to-one"形式保存外键

php - 使用 Doctrine 设置 "time"或 DateInterval

php - 如何在单个 super 映射类中创建 ManyToOne 关系