繁体   English   中英

需要一些认真的SQL查询优化(MySQL)

[英]Some Serious SQL Query Optimization Needed (MySQL)

这是我当前的查询:

SELECT IFNULL(sum(open_for), 0) total, count(IF(open_for > 0, 1, null)) wins, count(IF(open_for < 0, 1, null)) losses FROM `sport_points` WHERE (sportable_id = 1 and sportable_type = 'Team' and game_time > '2010-07-13 11:39:58 UTC'

它基本上返回以下聚合数据:

团队A

  • open_for
  • 合计:2000
  • 获胜:20
  • 损失:12

现在,假设表中还有大约6个其他列,我需要执行单独的查询来获取一个团队的所有特定于列的聚合数据。 例如:

SELECT IFNULL(sum(FINAL_FOR), 0) total, count(IF(open_for > 0, 1, null)) wins, count(IF(open_for < 0, 1, null)) losses FROM `sport_points` WHERE (sportable_id = 1 and sportable_type = 'Team' and game_time > '2010-07-13 11:39:58 UTC'

团队A

  • final_for
  • 合计:4000
  • 获胜:40
  • 损失:18

这种方法的问题在于,我必须为200多个团队中的所有列运行大约6个单独的查询。 这是一个严重的负载问题。

理想情况下,该查询将在一个查询中返回一个团队的所有特定于列的聚合数据。 结果看起来像这样:

团队A

  • 总计
  • open_for_wins
  • open_for_losses
  • final_for_total
  • final_for_wins
  • final_for_losses

...等等...

只是为了那些想要帮助的人的利益:

查询1:

SELECT
    IFNULL(sum(open_for), 0) total
    ,COUNT(IF(open_for > 0, 1, null)) wins
    ,COUNT(IF(open_for < 0, 1, null)) losses
FROM
    `sport_points`
WHERE
    sportable_id = 1
    AND sportable_type = 'Team'
    AND game_time > '2010-07-13 11:39:58 UTC'

查询2:

SELECT
    IFNULL(SUM(FINAL_FOR), 0) total
    ,COUNT(IF(open_for > 0, 1, null)) wins
    ,COUNT(IF(open_for < 0, 1, null)) losses
FROM
    `sport_points`
WHERE 
    sportable_id = 1
    AND sportable_type = 'Team'
    AND game_time > '2010-07-13 11:39:58 UTC'

所需的输出列:团队名称,typeofquery,值

其中typeofquery是以下之一:

  • 总计
  • open_for_wins
  • open_for_losses
  • final_for_total
  • final_for_wins
  • final_for_losses

从两列open_forfinal_for以及winslosses列中派生。

最初考虑问题时,我猜测中间表可能有助于使用GROUP BY子句进行处理。

例如

INSERT INTO
  temptable
SELECT
  teamname
  ,'open_for' type
  ,IFNULL(SUM(open_for), 0) total
  ,COUNT(IF(open_for > 0, 1, null)) wins
  ,COUNT(IF(open_for < 0, 1, null)) losses
FROM
  `sport_points`
WHERE
  sportable_id = 1
  AND sportable_type = 'Team'
  AND game_time > '...'
GROUP BY
  teamname

然后运行相同的查询,但求和final_for 现在,您的临时表包含如下行:

teamname, type, total, wins, losses
TEAM A, open_for, 100, 37, 63
TEAM A, final_for, 30, 10, 20
TEAM B, open_for, 12, 8, 4
TEAM B, final_for, 50, 49, 1

您的最终查询可以根据需要连接列。

我会将其作为单个查询来执行,该查询针对每个统计信息返回单独的 然后,如有必要,我将在我的应用程序代码中重组结果。 查询如下所示:

select teamname,
 sum(open_for) as open_total,
 count(if(open_for > 0, 1, null)) as open_wins,
 count(if(open_for < 0, 1, null)) as open_losses,
 sum(final_for) as final_total,
 count(if(final_for > 0, 1, null)) as final_wins,
 count(if(final_for < 0, 1, null)) as final_losses,
from sport_points
where sportable_id = 1
 and sportable_type = 'Team'
 and game_time > '...'
group by teamname

我建议这是一种更正统的关系方法,因此可以很容易地用SQL表示。 如果不是您的应用程序所需要的,那么进行调整的地方就是代码,它比SQL灵活得多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM