最大CPU使用率和使用MySQL查询执行> 60秒

时间:2012-06-11 00:52:00

标签: mysql sql linux left-join cpu-usage

当我第一次进行此查询并且表格相对较小时,它运行得非常快,但随着更新表大小的增加(现在大约6000行),随着时间的推移,查询极其缓慢且资源密集。我正在使用的服务器是来自linode.com的1GB RAM VPS,我实际上并没有等待足够长的时间来完成查询。

有趣的是,如果没有左连接中的额外条件(SELECT MAX(u2.time)),它将在< 0.5秒。

在查询运行时,我查看了mySQL的进程列表,并显示为“始终发送数据”

以下是查询:

SELECT 
  s.ID as sid, s.country AS country, 
  s.name AS name, s.ip AS ip, 
  u.connPlayers AS cp, u.maxPlayers AS mp
FROM servers AS s 

LEFT JOIN updates AS u 
  ON u.serverID = s.ID 
  AND u.time = 
      (SELECT MAX(u2.time) 
         FROM updates AS u2 
         WHERE u2.serverID = s.ID) 
ORDER BY RAND(MINUTE(NOW())) 
LIMIT 0,10

这是my.cnf文件:http://redream.co.nz/my.cnf

表格结构:

服务器表(20行 )

Field   Type
ID      int(10) Unique Key           
ip      varchar(200)                 
country varchar(2)               
name    varchar(600)             
motd    varchar(600)                 
desc    mediumtext               
version varchar(600)    

更新表格(6000行)

Field       Type
serverID    int(10)              
ping        int(10)              
time        int(14)              
uptime      int(10)              
connPlayers int(10)              
maxPlayers  int(10)              
uptime      int(14)

3 个答案:

答案 0 :(得分:2)

正在为Select MAX(...updates叉积的每一行运行子查询servers servers和{{{ 1}}然后再次updates。 MySQL的优化器不是很复杂。

更新:我的SQL有点生疏,但您可以尝试这样的事情:

updates

我没有方便的MySQL实例,因此您可能需要稍微调整一下才能使其正常工作。

Update2:仔细查看代码后,我认为此查询的成本高于我原来的估算值。更新了此答案的顶部。

答案 1 :(得分:0)

对于在您描述的平台上运行的MySQL,

6000行很小。

我要检查的第一件事是你的my.ini文件。您是否正在使用其中一个开箱即用的文件(现代服务器配置不正确)?如果是这种情况,最初的答案是编辑my.ini以为MySQL分配合理数量的内存。

如果您需要帮助,请发布my.ini文件(减去任何密码),因为有很多内容可能会导致这种性能下降。

此外,当查询运行得更快时(updates中的行少得多),查询返回的行数与当时updates中的行数相比较?

目前servers中有多少行?

答案 2 :(得分:0)

我不是MySQL专家,但我认为这适用于MySQL:

SELECT 
  s.ID as sid, s.country AS country, 
  s.name AS name, s.ip AS ip, 
  u.connPlayers AS cp, u.maxPlayers AS mp
FROM servers AS s 

LEFT JOIN (
    SELECT u.serverId, u.connPlayers, u.maxPlayers
    FROM updates u
    INNER JOIN (SELECT serverId, max(time) AS 'maxTime' FROM updates GROUP BY serverId) AS u2
        ON u.serverId = u2.serverId AND u.time = u2.maxTime 
) AS u ON u.serverID = s.ID 

ORDER BY RAND(MINUTE(NOW())) 
LIMIT 0,10

重要的变化是左连接现在包含以下子查询:

SELECT u.serverId, u.connPlayers, u.maxPlayers
FROM updates u
INNER JOIN (SELECT serverId, max(time) AS 'maxTime' FROM updates GROUP BY serverId) AS u2
    ON u.serverId = u2.serverId AND u.time = u2.maxTime 

此子查询再次包含一个子查询,并为每个serverId返回具有最大时间值的行。上面的子查询只执行一次,而不是跨产品中的每一行。