【问题标题】:symfony 3 iteration of array of objects too longsymfony 3对象数组的迭代太长
【发布时间】:2017-08-15 11:09:54
【问题描述】:

我得到了一个 symfony3 实体数组,总共 50000 个。我需要迭代这个数组并找到一些符合某些条件的实体。 代码如下:

$p_r = $em->getRepository('AppBundle:Product_region')->findall();//50000 elements in array
$rowid_2 = $product->getRowId();//some product entity

foreach($p_r as $pr){
   $rowid_1 = $pr->getProductid()->getRowId();

   if($rowid_1 == $rowid_2){
     $regions[] = $pr->getRegionid()->getName();
     $filial_name = $pr->getRegionid()->getFilial()->getName();

     if(!in_array($filial_name, $filials)){
       $filials[] =  $filial_name;
      }
   }
}

问题是迭代大约需要 1 秒,这非常长。完成操作大约需要 CPU 1 核心的 25%。我在不同的数字数组上对其进行了测试,发现迭代 50 000 个元素大约需要 0.002 秒。欢迎任何关于如何加快速度以及在哪里寻找延迟的想法。谢谢你。

【问题讨论】:

  • 根据我的经验,处理大量数据时最好不要使用对象。
  • 为什么不在数据库中进行比较?另外,你为什么要处理 id,通常你会让教义处理它们。直接使用它们很少是一个好主意。
  • 我应该将其转换为数组并在数组中进行搜索吗?如果我在实体中有外键关系,我怎样才能在没有对象的情况下到达那个连接的实体?
  • 正如@Yousi 已经说过的,您应该只从数据库中选择您需要的内容。在 PHP 端不要这样做,只需在查询本身中指定条件即可。
  • 看起来您正在使用延迟加载,这意味着您正在启动大量查询。例如每个 $pr->getRegionid()->getFilial()->getName();可能是查询一个区域对象,然后再查询一个子对象。您可以查看如何编写自定义查询来急切加载此类内容。但是,正如其他人所建议的,最好通过创建特定的数据库查询来完成。

标签: php symfony


【解决方案1】:

如果您想找到一些符合某些条件的实体,您可以使用 Doctrine 的 2 Criteria 来获取这些实体。

我发现它真的很有用。这里有 Doctrine 文档的链接:

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#filtering-collections

希望这会有所帮助。 :)

【讨论】:

    【解决方案2】:

    你有两个选择。创建一个区域/产品 Symfony Repository 并使用 QueryBuilder/DQL 创建一个 finder 函数,您可以指定要搜索的 ID 或使用 ArrayCollection 函数和条件来过滤结果。

    use Doctrine\Common\Collections\Criteria;
    $criteria = Criteria::create()->where(Criteria::expr()->eq('product_id', $product_id))->setFirstResult(0);
    $items = $p_r->matching($criteria);
    

    在该对象数组上迭代(foreach)将触发延迟加载,这将占用 CPU/内存。查看 Doctrine ArrayCollectionsCriteria 的代码

    【讨论】:

      猜你喜欢
      • 2011-01-07
      • 1970-01-01
      • 2021-06-22
      • 2019-07-13
      • 1970-01-01
      • 2014-07-11
      • 2017-03-29
      • 2019-02-27
      • 2017-07-30
      相关资源
      最近更新 更多