2

我已经阅读了一些关于 Doctrine 性能的文章,但是这个查询太慢了,似乎是错误的:

public function getBetRoundMainDataBuilder(BetRound $betRound){
        $qb = $this->createQueryBuilder('br')
                   ->select('br, uG, u, b, gG, g, t1, t2')
                   ->where('br.id = :bID')
                   ->setParameter('bID', $betRound->getId())
                   ->innerJoin('br.userGroup', 'uG')
                   ->innerJoin('uG.users', 'u')
                   ->innerJoin('br.gameGroup', 'gG')
                   ->leftJoin('gG.games', 'g')
                   ->leftJoin('g.team1', 't1')
                   ->leftJoin('g.team2', 't2')
                   ->leftJoin('br.bets', 'b' );
        return $qb;

    }

我知道它有很多联接,但我想我宁愿在一个查询中查询所有内容,而不是延迟加载所有相关数据。

我已经分析了代码,虽然这个查询没有选择太多的数据,但 array_shift 需要无穷无尽的数据:

分析数据

我错过了什么吗?我什至将 Hydration Mode 更改为 array,但仍然有问题。

更新: 我现在尝试只选择部分但没有改变太多:

           ->select('partial br.{id},
                     partial uG.{id},
                     partial u.{id, firstName, lastName, nickName, username, imageName},
                     partial b.{id, data},
                     partial gG.{id, title},
                     partial g.{id, data, date},
                     partial t1.{id, name, shortName, shortCode, logoName},
                     partial t2.{id, name, shortName, shortCode, logoName}')

下一步是拆分查询。

更新 2

它越来越好,我的视图中有几个区域需要不同的数据集。我试图将我的内容分成这些区域并相应地查询:

主要区域数据:

  • 下注轮
    • GamGroup(仅用于获得游戏)
      • 游戏
        • 团队
        • 投注(仅限当前用户!)

现在看起来像这样:

$qb = $this->createQueryBuilder('br')
        ->select(
            'partial br.{id},
            partial b.{id, data},
            partial gG.{id, title},
            partial g.{id, data, date},
            partial t1.{id, name, shortName, shortCode, logoName},
            partial t2.{id, name, shortName, shortCode, logoName}'
        )
        ->where('br.id = :bID')
        ->setParameter('bID', $betRound->getId())
        ->innerJoin('br.gameGroup', 'gG')
        ->leftJoin('gG.games', 'g')
        ->leftJoin('g.team1', 't1')
        ->leftJoin('g.team2', 't2')
        ->leftJoin('g.bets', 'b', 'WITH', 'b.user = :user')
        ->setParameter('user', $user->getId());
    return $qb;

第二个区域是 PointTable

$qb = $this->createQueryBuilder('br')
    ->select('br, b, u, uBs')
    ->where('br.id = :bID')
    ->setParameter('bID', $betRound->getId())
    ->leftJoin('br.bets', 'b')
    ->innerJoin('b.user', 'u')
    ->innerJoin('u.betroundStatus', 'uBs', 'WITH', 'uBs.betRound = :bID');

return $qb;

然后我有第三个区域,其中包含所有统计数据。它与第一个查询基本相同,但包括所有用户的投注。我现在不确定,如果我应该只使用一个查询所有用户投注的查询,或者,对于统计数据,为每个用户创建一个查询或以某种方式不同。

更新问题:

也许您看到我有一个名为 BetRound 的根实体,它可以启动所有查询(我的 BetRound 现在最多有 4 个完整的查询?我只是不知道如何在初始加载后将数据“添加”到我的关系中. 正如你所见,我的 BetRound 有几个加入“路径”。其中之一是“游戏路径”,如下所示:

  • BetRound -> GameGroup -> 游戏 -> Team1 & Team2
  • BetRound -> 用户组 -> 用户 -> UserBetRoundStatus
  • BetRound -> 投注

我需要所有这些数据,但是如何在一个具有正确关系的根实体中获取所有数据?如果我查询例如我是从例如 GameGroup 开始还是总是从我的根实体(=BetRound)开始?

4

2 回答 2

1

实际查询(PDOStatement::execute())只占总数的 3%。与数据库交互应该是脚本中最慢的部分,总执行时间的 3% 已经足够快了。

绝大多数时间被以下 3 个方法调用占用:

ArrayHydrator::hydrateRowData()   // 17%
AbstractHydrator::gatherRowData() // 39%
DateTimeType::convertToPHPValue() // 16%

如果你算上,它是总数的 72%。这是任何标准都无法接受的。

  • “补水”记录真的有必要吗?
  • 你能消除日期/时间转换吗?

你只需要追捕最大的罪人。剃掉脂肪。

于 2013-09-18T21:10:29.483 回答
1

我认为有很多左连接可能真的很慢。您应该重建此查询并删除那些左连接以提高一些性能。另外请检查数据库中是否正确创建了每个键和索引。

总之 - 这不是教义的错,而是查询。

于 2013-09-19T06:52:18.877 回答