Symfony2,Doctrine,为大量查询添加\ insert \ update最佳解决方案

时间:2013-05-16 16:08:35

标签: optimization symfony doctrine-orm

让我们假设我们有这个代码:

while (true)
{
    foreach($array as $row)
    {
       $item = $em->getRepository('reponame')->findOneBy(array('filter'));

       if (!$item)
       {
           $needPersist = true;
           $item = new Item();
       }

       $item->setItemName()
       // and so on ...

       if ($needPersist)
       {
           $em->persist();
       }
    }
    $em->flush();
}

所以,重点是代码将被执行很多次(而服务器不会死:))。我们想要优化它。每次我们:

  1. 从存储库中选择已经存入的条目。
  2. 如果输入不存在,请创建它。
  3. 设置新的(更新)变量。
  4. 应用操作(刷新)。
  5. 所以问题是 - 如何避免不必要的查询并优化“检查条目是否存在”?因为当有100-500个查询时它并不那么可怕......但是当它在一个while循环中达到1000-10000时 - 它太多了。

    PS:DB中的每个条目都有几列唯一(不仅仅是ID)。

2 个答案:

答案 0 :(得分:2)

  1. 不是一个一个地获取结果,而是使用一个查询加载所有结果。
  2. EG。 假设你的过滤器想要加载id 1,2,10。所以QB会是这样的:

    $allResults = ...
        ->where("o.id IN (:ids)")->setParameter("ids", $ids) 
        ->getQuery()
        ->getResults() ;
    
    1. “预告”这些结果,做好更新和冲洗的工作

    2. 执行该循环时,将这些已获取对象的ID保存在新数组中

    3. 使用array_diff将该数组与原始数组进行比较。现在你有第一次没有提取的ID

    4. 冲洗并重复:)

    5. 不要忘记$ em-> clear()来释放内存

    6. 虽然使用10.000条记录(dunno,从未测试过)时仍然会很慢,但是拥有2个大查询要比10.000个小查询要快得多。

答案 1 :(得分:0)

无论你是否需要它们在更新后保持不变,从数据库中检索10k +及以上的条目并将它们保存到php对象将需要太多的内存。在这种情况下,您最好回退到Doctrine DBAL Layer并触发纯SQL查询。