數據庫是MySQL與MyISAM引擎。GROUP BY查詢優化
表定義:
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 ;
我已成立的指數上(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
的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 |
有什麼辦法可以讓它更快?該表有大約800K條記錄。
編輯:我改變COUNT(id)
到COUNT(*)
的時間下降到0.08 - 0.12秒。我想我已經嘗試過在製作索引之前忘了在之後再次更改索引。
在解釋輸出的使用索引解釋的加快:
| rows | Extra |
| 168029 | Using where; Using index; Using temporary; Using filesort |
(方的問題:這是丟棄的5倍的正常)
有大約2000個用戶,所以最後的排序,即使它使用filesort,也不會影響性能。我嘗試沒有ORDER BY
,它仍然需要幾乎相同的時間。
計數(\ *)的性能比count(id)快得多的原因是MySQL對count(\ *)情況進行了特定的優化。計數(id)大小寫將通過數據第二遍來檢索結果,其中計數(\ *)使用現有的內部行計數器。儘可能使用計數(\ *)。 – 2011-05-20 15:30:43