【问题标题】:how to minimize the response time for this query in mysql如何在mysql中最小化此查询的响应时间
【发布时间】:2015-06-06 12:16:13
【问题描述】:

我有一张包含足球比赛列表的表格。它有 match_id、team a score、team 2 score、rounds、match_date 等列。

我需要数据库中该轮边距最高的所有行 margin是a队得分和b队得分之差。

我的查询是

SELECT *,( SELECT MAX(ABS((z.home_score - z.away_score))) 
FROM tblform_matches z 
WHERE YEAR(z.match_date) = YEAR(tblform_matches.match_date) 
    AND z.round = tblform_matches.round ) as highest_margin 
from tblform_matches where some condtion

这是一个简化的查询,其中某些条件是一个大查询字符串,用于根据过滤器选择一些指定的匹配项。

目前数据库中有大约 5000 个匹配项。

由于子查询,我的页面需要多花 4 秒才能加载。

每轮有9场比赛,每年有20多场比赛

我正在为 php 循环中的每个团队执行上述查询。我不能改变这件事。因为显示统计数据有很多计算。

对不起,如果我的问题不清楚,如果我错过了什么,我就在这里,因为我是 stakoverflow 的新手

提前致谢。

【问题讨论】:

  • 在 tblform_matches.match_date & tblform_matches.round 上添加二级索引。
  • 对不起,这个表在其他15个模块中使用,并且是相互关联的,所以我不允许对数据库进行任何更改。我只有读取权限才能显示统计数据

标签: php mysql


【解决方案1】:

这是您的查询:

SELECT m.*,
       (SELECT MAX(ABS((m2.home_score - m2.away_score))) 
        FROM tblform_matches m2
        WHERE YEAR(m2.match_date) = YEAR(m.match_date) AND
              m2.round = m.round
       ) as highest_margin 
from tblform_matches m
where some condition;

据推测,优化这一点的最佳方法是专注于 .那好吧。您将需要正确的索引。

索引显然是解决方案,但是由于year 函数,您遇到了问题。简单的解决方案是使用不等式:

SELECT m.*,
       (SELECT MAX(ABS((m2.home_score - m2.away_score))) 
        FROM tblform_matches m2
        WHERE m2.round = m.round
              (m2.match_date >= makedate(year(m.match_date), 1) and
               m2.match_date < makedate(year(m.match_date) + 1, 1)
              )                  
       ) as highest_margin 
from tblform_matches m
where some condtion;

子查询的最佳索引是tblform_matches(round, match_date, home_score, away_score)。前两列用于where 子句。后两个为select

注意:如果您对数据结构进行了两次相对较小的更改,这可能会更好。为匹配日期的年份添加一列(冗余,但对索引很重要)。并且,为分数之间的差值的绝对值添加一列。那么查询将是:

SELECT m.*,
       (SELECT MAX(score_diff)
        FROM tblform_matches m2
        WHERE m2.round = m.round and m2.matchyear = m.matchyear
       ) as highest_margin 
from tblform_matches m
where some condtion;

此查询的索引为:tblform_matches(round, matchyear, score_diff),查找速度应该很快。

编辑:

使用明确的join 可能会获得更好的性能:

SELECT m.*, m2.highest_margin
from tblform_matches m join
     (select MAX(ABS((m2.home_score - m2.away_score))) as highest_margin
      from tblform_matches m2
      group by year(m2.match_date), m2.round
     ) m2
     on year(m.match_date) = year(m2.match_date) and m2.round = m.round
where some condition;

【讨论】:

  • 感谢 Gordon,正如我在之前的评论中解释的那样,我无法对数据库进行任何更改。并且您没有索引的解决方案不会显着提高页面加载量。目前是 8 秒。
  • 主要问题是当循环为第一队进行时,它会检查该轮的每场比赛并计算每轮的最高边际,但当它第二次执行时,它会再次计算所有轮它为一队计算。每个团队都会发生这种情况
猜你喜欢
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-22
  • 1970-01-01
相关资源
最近更新 更多