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(仅用于获得游戏)
- 游戏
- 团队
- 下注(仅适用于当前用户!)
- 游戏
- 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
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%