当我第一次进行此查询并且表格相对较小时,它运行得非常快,但随着更新表大小的增加(现在大约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)
答案 0 :(得分:2)
正在为Select MAX(...
和updates
的叉积的每一行运行子查询servers
servers
和{{{ 1}}然后再次updates
。 MySQL的优化器不是很复杂。
更新:我的SQL有点生疏,但您可以尝试这样的事情:
updates
我没有方便的MySQL实例,因此您可能需要稍微调整一下才能使其正常工作。
Update2:仔细查看代码后,我认为此查询的成本高于我原来的估算值。更新了此答案的顶部。
答案 1 :(得分:0)
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返回具有最大时间值的行。上面的子查询只执行一次,而不是跨产品中的每一行。