mysql查询-使用group by时变慢

twh00eeo  于 2021-06-24  发布在  Mysql
关注(0)|答案(2)|浏览(587)

我花了4个小时在谷歌上搜索和尝试各种索引,mysqlyog,阅读,搜索等。我真的很感谢一些帮助。当我按添加组时,查询从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
c9qzyr3d

c9qzyr3d1#

所以你运行查询时没有 GROUP BY 在0.002秒内得到一个结果行。然后你又加了一句 GROUP BY (和 ORDER BY 显然)并在0.093秒内得到多个结果行。
为了产生这个结果,dbms必须以某种方式按用户对您的记录进行排序,或者为每个用户创建bucket,以便获得每个用户的记录计数、总和等。当然,这比遍历表、计算记录和无条件地求和值要花费更多的时间。最后,dbms甚至必须再次对这些结果进行排序。我一点也不奇怪这会持续很久。
此查询最合适的索引应该是:

create index idx on maths_score (lang, timestamp, user, correct);

这是一个覆盖索引,从中的列开始 WHERE ,继续中的列 GROUP BY 并以查询中使用的所有其他列结束。

5w9g7ksd

5w9g7ksd2#

请使用 SHOW CREATE TABLE ; 它更具描述性 DESCRIBE .
你有 INDEX(lang, TIMESTAMP) ? (为什么。)它可能对两个版本的查询都有帮助。
没有 GROUP BY ,你得到一排,对吗?与 GROUP BY ,你有很多行,对吗?你猜怎么着,传递更多的行需要更多的时间。
此外 GROUP BY 可能需要额外的分类。这个 ORDER BY 涉及排序,但在一种情况下,只有一行要排序,因此速度更快。如果有一百万 USERs ,然后 ORDER BY 将需要对一百万行进行排序,只需要交付500行。
请提供 EXPLAIN SELECT ... 对于每一个案例,你会看到我说的一些话。

相关问题