2014-09-04 129 views
0

所以,我有以下SQL优化MySQL查询

SELECT i.id, r.full_name, i.file_name, i.lat, i.lon, c.name as 
category_name,  
    NOW() - i.timestamp AS age,   
    (SELECT count(*) FROM votes WHERE image_id = i.id) as total_votes 
FROM images i INNER JOIN registrations r 
    ON i.user_id = r.id 
INNER JOIN categories c ON i.category_id = c.id 
WHERE i.moderated=1 
ORDER BY total_votes DESC 
LIMIT 25 

这在平均10-15秒对我的本地环境中运行。

删除ORDER BY部分将其降为0.02ish。

有什么方法可以加快主要语句中的排序?

更新1: 解释下面的查询。 Explain for query

更新2: 重写了查询,并增加了一些指标在

查询

SELECT votes.image_id, count(votes.id) as total_votes, 
     images.file_name, images.lat, images.lon, NOW() - images.timestamp AS age, 
     registrations.full_name, 
     categories.name 
FROM votes 
LEFT JOIN images 
    ON votes.image_id = images.id 
LEFT JOIN registrations 
    ON images.user_id= registrations.id 
LEFT JOIN categories 
    ON images.category_id = categories.id 
GROUP BY votes.image_id 
ORDER BY total_votes DESC 
LIMIT 25 

当前解释查询:

enter image description here

+2

首先发布EXPLAIN的输出以供查询 – Prix 2014-09-04 08:42:04

+0

您是否对所有加入的列都有索引? – DanFromGermany 2014-09-04 08:42:05

+0

@Prix - 更新与解释 – 2014-09-04 08:53:42

回答

1

你的子查询是次优的: )

SELECT i.id, r.full_name, i.file_name, i.lat, i.lon, c.name as 
category_name,  
    NOW() - i.timestamp AS age,   
    COUNT(*) as total_votes 
FROM images i INNER JOIN registrations r 
    ON i.user_id = r.id 
LEFT JOIN votes ON i.id = votes.image_id 

INNER JOIN categories c ON i.category_id = c.id 
WHERE i.moderated=1 
GROUP BY i.id 
ORDER BY total_votes DESC 
LIMIT 25 

如果这不起作用,您将不得不提供查询的表格结构和explain计划。

+0

解释添加到帖子...这是在13秒。 – 2014-09-04 08:52:03

+1

解释计划的列类型中的“ALL”表示完成全表扫描。你必须避免使用适当的索引。首先在您加入的列上添加索引。你应该坚持我的查询,你的(你可以在列select_type中看到)有一个从属子查询,这意味着子查询是为结果集的每一行执行的......非常慢。 – fancyPants 2014-09-04 09:06:16

2

在表images中创建一列“votes”。如果有投票的图像增量,如果有投票下降 - 减少。您可以并行查看表votes并检查是否有成功惰性然后增量。

有了这个,你将删除你的子选择。

之后,在images创建索引ORDER BY votes DESC和'moderated = 1`。

顺便说一句,你确定你的索引是okey吗? 还可以考虑INNER JOIN与类别。

+0

新增'votes'列可以通过'votes'表上的两个触发器来维护:'.. AFTER INSERT ON votes ..'(增值)和'.. AFTER DELETE ON votes ..'(递减值) – Rimas 2014-09-04 09:17:40

0

使用TEMP TABLES进行投票和注册表将帮助您加快查询速度。