0

我有以下查询,它计算 7 天的滚动平均值,但是由于WHERE b.serverId = a.serverId线路的原因,目前需要 4 分钟才能运行。我的问题是如何改进这个查询,以便它需要几毫秒到几秒?测试数据集约为 250k 行。

SELECT   a.serverId,
         s.serverName,
         a.playersOnline,
         DATE(a.pingTime) AS pingDate,
         Round( ( SELECT SUM(b.playersOnline) / COUNT(b.playersOnline)
                    FROM pings AS b
                   WHERE b.serverId = a.serverId AND 
                         DATEDIFF(a.pingTime, b.pingTime) BETWEEN 0 AND 6
                ), 2 ) AS '7dayMovingAvg'
    FROM pings AS a
    JOIN `server` AS s
      ON s.serverId = a.serverId
   WHERE a.serverId = 1
GROUP BY pingDate
ORDER BY a.pingTime;

表格:

服务器表

serverId - PK,索引

serverIp varchar

服务器端口 int(16)

服务器名称 varchar

启用 tinyint(1)

Ping 表

serverId FK,索引(参考服务器表)

pingTime 日期时间,索引

玩家在线 int(5)

玩家最大 int(5)

4

1 回答 1

0
           WHERE b.serverId = a.serverId AND 
                 DATEDIFF(a.pingTime, b.pingTime) BETWEEN 0 AND 6

了解“sargeable”。然后改为

           WHERE b.serverId = a.serverId AND 
                 b.pingTime BETWEEN a.pingTime
                                AND a.pingTime - INTERVAL 6 DAY

(注意:我可能算错了)

然后添加这个“复合”索引:

INDEX(serverId, pingTime)

这不计算:

GROUP BY pingDate
ORDER BY a.pingTime

你可能想要

GROUP BY pingDate
ORDER BY pingDate

如需进一步讨论,请提供SHOW CREATE TABLEEXPLAIN SELECT ...

您是否正在重新计算所有日子的所有移动平均线?昨天的不会变吧?将其存储在另一个表中。然后只计算每晚的当前平均值。

(“指数移动平均线”更容易计算,可能更快。考虑切换到它。)

于 2020-08-06T05:30:03.257 回答