用于计算另一个表中的用户结果的MySQL子查询是sloooooooow

时间:2013-11-29 15:11:22

标签: mysql sql subquery

我有一个MySQL查询,我正在运行以返回用户并从其他表中计算相应的培训结果,通常这些是在应用程序前端50中一次显示的结果,但是有很多结果查询变得非常慢。

如果我在MySQL查询运行后使用PHP附加数据但是这会感觉很糟糕且很脏并且也阻止我能够对结果列进行排序,那么事情会无限好。即我希望能够按照他们拥有的结果数量对用户进行排序。 :)

这是我当前的SQL查询,它的所有荣耀:

SELECT DISTINCT users.email,
(SELECT COUNT(r.result_id)
    FROM programmes_results r
    WHERE ((r.client_id=users.client_id) AND (r.email=users.email))
) as results
FROM users
INNER JOIN users_groups ON users_groups.user_id=users.id
WHERE users.client_id='130' AND users_groups.group_id IN (5)
ORDER BY email asc
LIMIT 10

这需要4秒的时间来执行,这显然是完全的裤子。我确信必须有另一种方法来返回这些额外的数据,而不会产生这样的性能损失,但我在这里已经达到了我的知识范围。

任何指针都非常感激。 :)

3 个答案:

答案 0 :(得分:2)

尝试类似

的内容
SELECT users.email, COUNT(r.result_id) as results
FROM users
INNER JOIN users_groups ON users_groups.user_id=users.id
INNER JOIN programmes_results r on ((r.client_id=users.client_id) AND (r.email=users.email))
WHERE users.client_id='130' AND users_groups.group_id IN (5)
group by users.email
ORDER BY users.email asc
LIMIT 10

答案 1 :(得分:1)

我怀疑问题是你在programmes_results上没有正确的索引。你需要一个覆盖client_id和email的索引,有两个单独的索引对它们没什么帮助,因为它只能使用其中一个,比如client_id,然后必须扫描所有匹配的行正确的电子邮件。尝试:

CREATE INDEX id_email ON programmes_results (client_id, email)

然后再次运行您的查询。

答案 2 :(得分:0)

尝试

SELECT u.email, 
       COUNT(r.result_id) AS results
FROM users u
INNER JOIN users_groups ug ON ug.user_id = u.id
INNER JOIN programmes_results r ON r.client_id = u.client_id 
                                AND r.email = u.email
WHERE u.client_id = '130' AND ug.group_id IN (5)
GROUP BY u.email
ORDER BY u.email asc
LIMIT 10