【问题标题】:query becomes slow with GROUP BY使用 GROUP BY 查询变慢
【发布时间】:2018-01-15 20:31:17
【问题描述】:

我花了 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

【问题讨论】:

  • 重要的是要理解您的“order by”子句要求 mysql 在发出任何内容之前对所有输出进行排序,因为该子句包含计算值。
  • 要提高同一队列的性能,您需要创建 3 个索引。 (我认为当前的索引不正确)。 1- TIMESTAMP + lang 上的 Index1 2- USER 上的 index2 和 3- index3 上正确的。注意:索引中列的顺序很重要。

标签: mysql performance indexing group-by


【解决方案1】:

请使用SHOW CREATE TABLE;它比DESCRIBE 更具描述性。

你有INDEX(lang, TIMESTAMP)吗? (Why.) 这可能对两个版本的查询都有帮助。

没有GROUP BY,你会得到一排,对吗?使用GROUP BY,你会得到很多行,对吗?猜猜看,交付更多行需要更多时间。

此外,GROUP BY 可能涉及一个额外的排序。 ORDER BY 涉及排序,但在一种情况下,只有 1 行要排序,因此速度更快。如果有一百万个USERs,那么ORDER BY 将需要对一百万行进行排序,只交付500 行。

请为每个案例提供EXPLAIN SELECT ... -- 你会看到一些我在说什么。

【讨论】:

    【解决方案2】:

    因此,您在没有 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 中的列继续,并以查询中使用的所有其他列结束。

    【讨论】:

      猜你喜欢
      • 2013-05-30
      • 2021-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-03
      • 2018-09-07
      • 2019-09-12
      相关资源
      最近更新 更多