GROUP BY查询优化

ype*_*eᵀᴹ 6 mysql myisam group-by query-optimization

数据库是带有MyISAM引擎的MySQL.

表定义:

CREATE TABLE IF NOT EXISTS  matches  (
   id  int(11) NOT NULL AUTO_INCREMENT,
   game  int(11) NOT NULL,
   user  int(11) NOT NULL,
   opponent  int(11) NOT NULL,
   tournament  int(11) NOT NULL,
   score  int(11) NOT NULL,
   finish  tinyint(4) NOT NULL,
  PRIMARY KEY ( id ),
  KEY  game  ( game ),
  KEY  user  ( user ),
  KEY  i_gfu ( game , finish , user )
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3149047 ;
Run Code Online (Sandbox Code Playgroud)

我已设置索引,(game, finish, user)但此GROUP BY查询仍需要0.4 - 0.6秒才能运行:

SELECT user AS player
     , COUNT( id ) AS times
FROM matches
WHERE finish = 1
  AND game = 19
GROUP BY user
ORDER BY times DESC
Run Code Online (Sandbox Code Playgroud)

EXPLAIN输出:

| id | select_type | table   | type | possible_keys | key   | key_len | 
|  1 |  SIMPLE     | matches |  ref | game,i_gfu    | i_gfu |    5    | 

|  ref        |   rows |   Extra                                      |
| const,const | 155855 | Using where; Using temporary; Using filesort |
Run Code Online (Sandbox Code Playgroud)

有什么方法可以让它更快吗?该表有大约800K的记录.


编辑:我改变COUNT(id)COUNT(*),时间下降到0.08 - 0.12秒.我想在制作索引之前我已经尝试过了,之后忘了再次更改它.

在explain输出中,Using索引解释了加速:

|   rows |   Extra                                                   |
| 168029 | Using where; Using index; Using temporary; Using filesort |
Run Code Online (Sandbox Code Playgroud)

(旁边的问题:这是正常的5倍下降吗?)

大约有2000个用户,所以最后排序,即使它使用filesort,也不会影响性能.我试过没有ORDER BY,它仍然需要几乎相同的时间.

mat*_*att 7

摆脱'游戏'键 - 它与'i_gfu'是多余的.由于'id'是唯一计数(id),因此只返回每个组中的行数,因此您可以删除它并将其替换为count(*).尝试这种方式并粘贴EXPLAIN的输出:

SELECT user AS player, COUNT(*) AS times
FROM matches
WHERE finish = 1
AND game = 19
GROUP BY user
ORDER BY times DESC
Run Code Online (Sandbox Code Playgroud)


ic3*_*3rg 1

EXPLAIN 验证(game, finish, user)查询中使用了索引。对我来说这似乎是最好的索引。会不会是硬件问题?您的系统 RAM 和 CPU 是多少?