我有一个简单的MyISAM表,类似于以下内容(为便于阅读而修剪 - 实际上有更多列,所有列都是恒定宽度,其中一些可以为空):MySQL:优化COUNT(*)和GROUP BY
CREATE TABLE IF NOT EXISTS `history` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`time` int(11) NOT NULL,
`event` int(11) NOT NULL,
`source` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `event` (`event`),
KEY `time` (`time`),
);
目前表格中只包含大约600万行(其中目前约16下方匹配查询),但是这预计将增加。给定一个特定的事件ID并按来源分组,我想知道在特定的时间间隔内有多少个具有该ID的事件被记录。对于查询的答案可能是沿着“今天,事件X对于源A发生120次,对于源B发生105次,对于源C发生900次”。
我编制的查询确实执行了这个任务,但它执行起来很糟糕,在时间跨度设置为“所有时间”时需要花费一分多钟才能执行,而在一周之内只需要超过30秒钟:
SELECT COUNT(*) AS count FROM history
WHERE event=2000 AND time >= 0 AND time < 1310563644
GROUP BY source
ORDER BY count DESC
这不是实时使用,所以即使查询需要一两秒钟,这将是罚款,但几分钟没有。在解释查询给出以下,其中最困扰我的原因很明显:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE history ref event,time event 4 const 160399 Using where; Using temporary; Using filesort
我曾与各种多列索引(如(活动时间))试验,但没有改善。这似乎是一个这样的常见用例,我无法想象没有合理的解决方案,但我的谷歌搜索都归结为我已有的查询版本,没有关于如何避免临时(即使是,为什么表现如此糟糕)。
有什么建议吗?
正如您可以从顶部架构看到的,除了我尝试的多列索引之外,事件和时间都是分别索引的。 – pjohansson
对不起,我错过了。我对使用'KEY'关键字指定'INDEX'的语法并不熟悉......如何将'INDEX'添加到'source'? –
责备phpmyadmin的导出功能 - 我也不习惯。 :)此外,对源代码进行索引在我的测试中没有提供额外的好处。 – pjohansson