[英]optimizing a slow mysql query
下面的mysql查询执行需要40秒,这太多了
我该如何优化呢?
SELECT
downloads.*,
COUNT(DISTINCT comment.id) AS commentsNum,
AVG(users_votes.rate) AS score,
COUNT(DISTINCT users_votes.id) AS rateNum,
COUNT(DISTINCT users_download.id) AS downloadsNum
FROM downloads
LEFT JOIN (
SELECT * FROM comment WHERE type='download'
) comment ON downloads.id = comment.typeID
LEFT JOIN (
SELECT * FROM users_votes WHERE section='download' AND rate>0
) users_votes ON downloads.id = users_votes.voteID
LEFT JOIN (
SELECT id,downloadID FROM users_download GROUP BY userID,downloadID
) users_download ON downloads.id = users_download.downloadID
GROUP BY downloads.id
EXPLAIN的结果:
您应通过download_id将结果集归为join。
SELECT
downloads.*,
comment.commentsNum,
users_votes.AvgScore,
users_votes.rateNum,
users_download.downloadsNum
FROM downloads
LEFT JOIN (
SELECT TypeID,COUNT(*) AS commentsNum FROM comment WHERE type='download' GROUP BY TypeID
) comment ON downloads.id = comment.typeID
LEFT JOIN (
SELECT voteID,AVG(rate) AS AvgScore,COUNT(*) AS rateNum FROM users_votes WHERE section='download' AND rate > 0 GROUP BY voteID
) users_votes ON downloads.id = users_votes.voteID
LEFT JOIN (
SELECT downloadID,COUNT(userID) AS downloadsNum FROM users_download GROUP BY downloadID
) users_download ON downloads.id = users_download.downloadID
从您的解释来看, users_download
表似乎是罪魁祸首。 该查询被迫从该表中扫描10万行,我猜这是由于GROUP BY
与未命中索引相结合。
“使用文件排序”是一个警告信号,因为它必须将表的某些部分写入磁盘才能进行排序(可能是再次分组)。 众所周知,磁盘非常慢。
我不确定您要尝试做的是什么,但是GROUP BY
通常很昂贵,因此,如果您不使用GROUP BY
即可重写查询,则可能会提高性能。 否则,请尝试创建一个索引,该索引可以帮助MySQL查找正确的行而无需扫描表的大部分内容。
这是优化的查询
为什么这个查询执行得很快?
但是旧查询执行得很慢?
专家程序员分析:)
SELECT
downloads.*,
comment.commentsNum AS commentsNum,
users_votes.AvgScore AS score,
users_votes.rateNum AS rateNum,
users_download.downloadsNum AS downloadsNum
FROM downloads
LEFT JOIN (
SELECT typeID,COUNT(id) AS commentsNum FROM comment WHERE type='download' GROUP BY typeID
) comment ON downloads.id = comment.typeID
LEFT JOIN (
SELECT voteID, AVG(rate) AS AvgScore,COUNT(id) AS rateNum FROM users_votes WHERE section='download' AND rate > 0 GROUP BY voteID
) users_votes ON downloads.id = users_votes.voteID
LEFT JOIN (
SELECT id,downloadID,COUNT(id) AS downloadsNum FROM users_download WHERE id IN (SELECT MIN(id) FROM users_download GROUP BY userID,downloadID) GROUP BY downloadID ORDER BY downloadID
)
users_download ON downloads.id = users_download.downloadID
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.