我有一些令人讨厌的查询,其中有几个子选项确实让它变慢了。我已经在缓存查询,但其结果经常更改,查询结果将显示在高流量页面上。
SELECT user_id, user_id AS uid, (SELECT correct_words
FROM score
WHERE user_id = `uid`
ORDER BY correct_words DESC, incorrect_words ASC
LIMIT 0, 1) AS correct_words,
(SELECT incorrect_words
FROM score
WHERE user_id = `uid`
ORDER BY correct_words DESC, incorrect_words ASC
LIMIT 0, 1) AS incorrect_words
FROM score
WHERE user_id > 0
AND DATE(date_tested) = DATE(NOW())
GROUP BY user_id
ORDER BY correct_words DESC,incorrect_words ASC
LIMIT 0,7
查询的目标是为当天的用户挑选最高分,但只显示该用户的最高得分实例而不是所有分数(例如,如果一个用户实际上有4个那天排名前十的分数,我只想显示该用户的最高分并删除剩下的分数)
尽我所能,我还没有以任何其他方式复制此查询的结果。现在它的平均运行时间大约是2秒,但我担心随着桌子变大,这可能会大大增加。
有什么想法吗?
答案 0 :(得分:2)
试试这个:
子查询基本上以正确的顺序返回所有分数的结果集,并且外部查询将第一次出现。在MySQL中进行分组时,未分组的列将返回相当于FIRST(列)的值:第一次出现的值。
SELECT user_id, correct_words, incorrect_words
FROM
( SELECT user_id, correct_words, incorrect_words
FROM score
WHERE user_id>0
AND DATE(date_tested)=DATE(NOW())
ORDER BY correct_words DESC,incorrect_words ASC
)
GROUP BY user_id
LIMIT 0,7
答案 1 :(得分:1)
correct_words
和incorrect_words
的子查询可能真的会扼杀您的表现。在最坏的情况下,MySQL必须为它考虑的每一行执行这些查询(而不是它返回的每一行!)。不要使用标量子查询,而是考虑重写您的查询以使用JOIN
- 变体。
此外,按DATE(date_tested)=DATE(NOW())
过滤可能会阻止MySQL使用索引。我不相信MySQL的任何生产版本都允许使用基于函数的索引。
确保您在过滤和排序的所有列上都有索引。如果通过匹配您的查询过滤或排序的列,MySQL可以使用多列索引,例如, CREATE INDEX score_correct_incorrect_idx ON score ( correct_words DESC, incorrect_words ASC );
将是候选索引,但MySQL可能会选择不使用它,具体取决于它创建的执行计划及其对表大小的估计。