Php 可笑的慢条令质疑

Php 可笑的慢条令质疑,php,mysql,symfony,doctrine-orm,Php,Mysql,Symfony,Doctrine Orm,我已经读过一些关于条令性能的文章,但这一查询速度太慢,似乎完全错了: public function getBetRoundMainDataBuilder(BetRound $betRound){ $qb = $this->createQueryBuilder('br') ->select('br, uG, u, b, gG, g, t1, t2') ->where('br.id = :

我已经读过一些关于条令性能的文章,但这一查询速度太慢,似乎完全错了:

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;

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

我已经分析了代码,尽管此查询没有选择太多数据,但数组移位需要无限时间:

我错过什么了吗?我甚至将水合模式更改为数组,但仍然存在问题

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

           ->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

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

更新问题:

也许你会看到我有一个名为BetRound的根实体,它可以启动所有的查询(我现在最多有4个来自BetRound的复杂查询? 我只是不知道如何在初始加载后将数据“添加”到关系中。 正如您可能看到的,我的BetRound有几个连接“路径”。其中一个是“游戏路径”,看起来像:

  • BetRound->GameGroup->Games->Team1和Team2
  • BetRound->UserGroup->Users->UserBetRoundStatus
  • BetRound->Bets
我需要所有这些数据,但如何获得一个具有正确关系的根实体中的所有数据?如果我查询,例如,我是从游戏组开始,还是始终从根实体(=BetRound)开始?

实际查询(
PDOStatement::execute()
)只占总时间的3%。考虑到与数据库的交互应该是脚本中最慢的部分,3%的总执行时间非常快

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

ArrayHydrator::hydrateRowData()   // 17%
AbstractHydrator::gatherRowData() // 39%
DateTimeType::convertToPHPValue() // 16%
如果你算起来,这是总数的72%,这是任何标准都无法接受的

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

你只需要追踪最大的罪人。去掉脂肪。

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


总之,这不是条令的错,而是查询的错。

好吧,你选择了很多数据。试着只选择你需要的字段,而不是整个实体。还要获取执行的SQL并对其运行解释。我试着只将选择更改为必要的字段,但随后我在主结果数组中得到了这些字段的ArrayResult,al虽然所选数据将位于相关实体中。但您将希望解耦查询…7个连接在水合时更为多余。我通常的目标是最多3个连接,在极端情况下为5个连接。在您的情况下,可能会超过7个连接(因为可能存在多个关系)。您可以从在上查询连接开始分别为“br.userGroup”和“br.gameGroup”(每个查询将按BetRound ID进行筛选)并重申从那开始的努力。这不会改变水合仍然需要很多时间的事实,所以我肯定会使用数组而不是实体。嗨,我暂时玩了ArrayHydration,现在再次使用对象水合。但结果并不是绝对释放。
ArrayHydrator::hydrateRowData()   // 17%
AbstractHydrator::gatherRowData() // 39%
DateTimeType::convertToPHPValue() // 16%