【问题标题】:Symfony mass hydration from one repository to anotherSymfony 大规模水合从一个存储库到另一个存储库
【发布时间】:2018-09-04 15:03:35
【问题描述】:

我的下一个代码可以正常执行,但它需要太多时间...有什么办法可以使用 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 分配新值。 有什么想法吗?

【问题讨论】:

  • 我会建议你一些改进点
  • 您的 csv 中的平均行数是多少?

标签: symfony doctrine hydration


【解决方案1】:

你可以直接使用CsvEncoder而不使用序列化器,你使用的是没有反规范化的解码。

我区分了两种提高性能的方法

无代码更改

您应该将ref-dos 对索引到您的数据库中,这确实会增加查询时间。

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

一个大查询

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

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

之后你可以对你的数据库做ONE大查询,避免一个查询/行,IMO非常耗时。

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

这样IMO是最好的一个


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

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


如果您真的想快速运行,您可以使用原始 SQL 并避免学说实体水合。但我不建议你这样做

【讨论】:

    猜你喜欢
    • 2012-10-05
    • 2017-11-03
    • 1970-01-01
    • 2020-10-25
    • 2019-07-18
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    相关资源
    最近更新 更多