Symfony2,Doctrine,添加\插入\更新大量查询的最佳解决方案

问题描述 投票:0回答:2

假设我们有这段代码:

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. 应用操作(刷新)。

所以问题是 - 如何避免不必要的查询并优化“检查条目是否存在”?因为当有 100-500 个查询时,它并没有那么可怕......但是当一个 while 循环达到 1000-10000 个查询时 - 就太多了。

PS:数据库中的每个条目在几列中都是唯一的(不仅仅是 ID)。

php symfony optimization doctrine-orm
2个回答
2
投票
  1. 不要逐一获取结果,而是通过一个查询加载所有结果。

例如。 假设您的过滤器想要加载 ids 1, 2, 10。所以 QB 会是这样的:

$allResults = ...
    ->where("o.id IN (:ids)")->setParameter("ids", $ids) 
    ->getQuery()
    ->getResults() ;
  1. “foreach”这些结果,完成更新和刷新它们的工作

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

  3. 使用 array_diff 将该数组与原始数组进行比较。现在你有了第一次未获取的 id

  4. 冲洗并重复:)

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

虽然在处理 10.000 条记录时仍然会很慢(不知道,从未测试过),但 2 个大查询会比 10.000 个小查询快得多。


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.