我花了4个小时谷歌搜索和尝试各种索引,mysqlyog,阅读,搜索等。我真的很感激一些帮助。当我添加GROUP BY时,查询从0.002秒更改为0.093秒。这是正常的吗?或者我可以更改索引和/或查询吗?非常感谢一些帮助。希望如果我得到答案,我可以利用这些知识向前推进......先谢谢。
表:
uniqueid int(11) NO PRI NULL auto_increment
ip varchar(64) YES NULL
lang varchar(16) YES MUL NULL
timestamp int(11) YES MUL NULL
correct decimal(12,2) YES NULL
user varchar(32) YES NULL
timestart int(11) YES NULL
timeend int(11) YES NULL
speaker varchar(64) YES NULL
postedAnswer int(32) YES NULL
correctAnswerINT int(32) YES NULL
查询:
SELECT
SQL_NO_CACHE
user,
lang,
COUNT(*) AS total,
SUM(correct) AS correct,
ROUND(SUM(correct) / COUNT(*) * 100) AS score,
TIMESTAMP
FROM
maths_score
WHERE TIMESTAMP > 1
AND lang = 'es'
GROUP BY USER
ORDER BY (
(SUM(correct) / COUNT(*) * 100) + SUM(correct)
) DESC
LIMIT 500
解释延伸:
id select_type table type possible_keys key key_len ref rows filtered Extra
------ ----------- ----------- ------ ------------------------- -------------- ------- ------ ------ -------- ---------------------------------------------------------------------
1 SIMPLE maths_score ref scoretable,fulltablething fulltablething 51 const 10631 100.00 Using index condition; Using where; Using temporary; Using filesort
当前索引(我尝试了很多)
Keyname Type Unique Packed Column Cardinality Collation Null Comment
uniqueid BTREE Yes No uniqueid 21262 A No
scoretable BTREE No No timestamp 21262 A Yes
lang 21262 A Yes
fulltablething BTREE No No lang 56 A Yes
timestamp 21262 A Yes
user 21262 A Yes
答案 0 :(得分:1)
请使用SHOW CREATE TABLE
;它比DESCRIBE
更具描述性。
你有INDEX(lang, TIMESTAMP)
吗? (Why.)它可能有助于两个版本的查询。
没有GROUP BY
,你会得到一行,对吗?使用GROUP BY
,您会收到很多行,对吗?猜猜是什么,需要更多时间来提供更多行。
此外,GROUP BY
可能涉及额外的排序。 ORDER BY
涉及一种排序,但在一种情况下,只有一行要排序,因此更快。如果有一百万USERs
,那么ORDER BY
将需要排序一百万行,只能提供500行。
请为每个案例提供EXPLAIN SELECT ...
- 您会看到我正在说的一些。
答案 1 :(得分:0)
因此,您在没有GROUP BY
的情况下运行查询,并在0.002秒内得到一个结果行。然后你添加了GROUP BY
(显然是ORDER BY
),最后得到了0.093秒的多个结果行。
为了产生这个结果,DBMS必须以某种方式按用户命令您的记录或为每个用户创建存储桶,以便获得每个用户的记录计数,总和等。当然,这比在表中运行,计算记录和无条件地总结一个值要花费更多的时间。最后,DBMS必须再次对这些结果进行排序。我跑的时间并不长,我并不感到惊讶。
此查询最合适的索引应为:
create index idx on maths_score (lang, timestamp, user, correct);
这是一个覆盖索引,从WHERE
中的列开始,继续GROUP BY
中的列,并以查询中使用的所有其他列结束。