左连接会导致性能大幅下降。如何修复它

Posted

技术标签:

【中文标题】左连接会导致性能大幅下降。如何修复它【英文标题】:Left join causes huge performance drop. How to fix it 【发布时间】:2019-10-17 11:52:03 【问题描述】:

我有 3 个单独的查询,当我通过左连接合并它们时,性能下降很大

任何想法为什么会发生或如何解决这个问题?

这里是查询

第一次查询

SELECT MONEY,
       AccountLevel,
       BadgeCount,
       EloWin,
       TournamentOfficBattleTotal,
       MaximumTowerLevel,
       NpcBattleVictoryCount
FROM table_2
WHERE table_2.UserId = 465903

第二次查询

  SELECT COUNT(DISTINCT table_1.PokemonId) AS PokedexOwnage
  FROM table_1 WHERE UserId = 465903

第三次查询

  SELECT COUNT(*) AS PokedexEvent
  FROM table_3 WHERE UserId = 465903

这是我将所有 3 个合并为一个的解决方案

  SELECT MONEY,
         AccountLevel,
         BadgeCount,
         COUNT(DISTINCT table_1.PokemonId) AS PokedexOwnage,
         COUNT(DISTINCT table_3.PokemonId) AS PokedexEvent,
         EloWin,
         TournamentOfficBattleTotal,
         MaximumTowerLevel,
         NpcBattleVictoryCount
  FROM table_2
  LEFT JOIN table_1 ON table_1.UserId = table_2.UserId
  LEFT JOIN table_3 ON table_3.UserId = table_2.UserId 
  WHERE table_2.UserId = 465903
GROUP BY AccountLevel,
         BadgeCount,
         EloWin,
         TournamentOfficBattleTotal,
         MaximumTowerLevel,
         NpcBattleVictoryCount,
         MONEY

当我通过执行计划进行比较时,前 3 个查询与最后一个查询的相对成本为 0%

【问题讨论】:

如果您提供查询计划,Paste the Plan 是一种比图像更好的方法。特别是当我们无法检查这些图像并且图像没有提供完整的计划时。 ?????? 【参考方案1】:

聚合之前加入。一种方法是使用相关子查询:

SELECT MONEY, AccountLevel, BadgeCount, EloWin,
       TournamentOfficBattleTotal, MaximumTowerLevel, NpcBattleVictoryCount,
       (SELECT COUNT(DISTINCT t1.PokemonId)
        FROM table_1 t1
        WHERE t1.UserId = t2.UserId
       ) as PokedexOwnage,
       (SELECT COUNT(*)
        FROM table_3 t3
        WHERE t1.UserId = t3.UserId
       ) as PokedexEvent
FROM table_2 t2
WHERE t2.UserId = 465903;

这可能会很好。但为了获得更好的性能,请确保您在 table_2(UserId, PokemonId)table_3(UserId) 上有索引。

【讨论】:

以上是关于左连接会导致性能大幅下降。如何修复它的主要内容,如果未能解决你的问题,请参考以下文章

SQL 连接与单表:性能差异?

对 2 种字体使用 @font-face 会导致速度大幅下降

JavaScript 引擎「V8」发布 8.0 版本,内存占用量大幅下降

SQL Db2 中的左连接而不是不存在

SQL Server 子查询会导致性能损失吗?

将 GetDC 代码移动到线程中时性能大幅下降