【问题标题】:Symfony2 / Doctrine queries in loopsSymfony2 / Doctrine 循环查询
【发布时间】:2015-04-11 13:59:41
【问题描述】:

我正在清理其他人编写的一些旧代码,因为我们遇到了超时问题,尤其是那些正在突破我们系统极限的客户。

我知道这是一种反模式,并且代码中充满了这种变化:

$userIDs = [100,101,107,208, ...]; // tons of users, but not all users in a company.
$companyID = 4356;

foreach ($userIDs as $id) {
    $user = $em->getRepository('AdminBundle:Users')
                ->getUser($id, $companyId);          
    $user->removeGroup($group);
    $em->persist($user);
    $em->flush();
}

它只会导致对每个用户的查询,这会使服务器超时(分析器显示数百个查询)。增加超时确实有效,但该解决方案不能很好地扩展......并且导致我喝咖啡的时间比健康的要多。

将其重写为单个更新查询的正确、高效、symfony-ey 方式是什么?

【问题讨论】:

  • 请告诉我用户id和公司id是怎么设置的。
  • 来自会话数据和请求参数。我仍在尝试破译其中的大部分内容,但它是一个执行“管理面板”的控制器——将权限、用户和组耦合在一起。 “组”页面上的表单有一堆复选框和下拉菜单,您可以在其中将公司中的任意数量的用户添加到该组,并设置各种操作的权限。问题是,有些公司拥有数百个用户和数百个组。

标签: php mysql symfony doctrine-orm anti-patterns


【解决方案1】:

两种可能:

  1. 使用带有whereIn 语句的查询构建器,绑定到用户ID 数组和带有公司ID 的andWhere

  2. 如果目标是执行 DELETE,并且之后您没有对该实体进行任何其他使用,则可以使用精心制作的 DQL 请求。

如果需要,我可以编辑并添加更多助手。

【讨论】:

  • 太棒了,这很好用!现在我只剩下一个有问题的循环了,里面还有第二个循环。它遍历所有用户,然后遍历所有当前关联的组 (FOSuserbundle) 以删除它们,然后重新分配新组。通过删除外部循环并执行 where IN(),我可以减少到 1000 个查询,而不是一百万个查询 (1000^2)。你知道有没有办法做 $user->removeallgroups();?
  • 我不知道“组”到底是什么,但如果它是一个 ArrayCollection,那么您可以使用 $user->getGroups()->clear(); 来执行 removeAllGroups;我想。
  • 是的,arraycollection。但是我仍然收到很多查询,因为其中一部分仍在循环中。看这个例子:pastebin.com/raw.php?i=MwDqugzw “getUsersFromArray” 是我快速添加的存储库中的一个函数,因此我可以获取传递一组用户 ID,并使用“->where(”u.id IN(:userids) 选择它们和...”等
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-11
相关资源
最近更新 更多