我在MySQL中有两个表。一个包含用户,另一个包含交易数据。
我正在努力寻找获利最多的前50位用户。
CREATE TABLE IF NOT EXISTS `t_logs` (
`tid` int(11) NOT NULL AUTO_INCREMENT,
`userid` int(11) NOT NULL,
`amount` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`tid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
CREATE TABLE IF NOT EXISTS `t_users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`login` varchar(100) NOT NULL,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
查询:
SELECT *, (SELECT SUM(amount) FROM `t_logs` WHERE userid=u.id LIMIT 0,1) AS profit
FROM `t_users` u
ORDER BY profit DESC
LIMIT 0,50
现在的问题是,如果我在t_users表中有1000个条目,在t_logs表中有3000个事务,那么这个查询在使用Apache和2GB内存的VDS上需要25秒,或者在使用XAMPP的本地计算机上需要9秒(我有16GB的RAM。。
问题是:我还能做些什么来优化这一切吗?也许将表引擎从MyISAM更改为其他内容?或者也许我的查询无效?或者唯一的解决方案是为VDS添加更多RAM。
如果我们尝试添加10000个用户和10000个日志,则查询在VDS上需要250秒。如果我希望拥有超过50000个用户和超过100万个日志,我有哪些选择?
答案 0 :(得分:1)
您应该使用LEFT JOIN
而非GROUP BY
而不是子查询,并且您需要t_logs.userid
上的索引:
SELECT u.*, SUM(l.amount) AS profit
FROM t_users u
LEFT JOIN t_logs l
ON l.userid = u.id
GROUP BY u.id
ORDER BY profit DESC
LIMIT 50
答案 1 :(得分:1)
SELECT u.* , p.profit
FROM `t_users` u
LEFT JOIN (
SELECT userid, SUM(amount) as profit FROM `t_logs` GROUP BY userid) AS p
ON p.userid=u.id
ORDER BY p.profit DESC
LIMIT 0,50