【发布时间】:2011-07-13 13:37:32
【问题描述】:
我有一个简单的 MyISAM 表,类似于以下内容(为了便于阅读而进行了修剪——实际上,有更多列,所有列的宽度都是恒定的,其中一些可以为空):
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`),
);
目前该表仅包含大约 6,000,000 行(其中当前大约 160,000 行与下面的查询匹配),但预计会增加。给定一个特定的事件 ID 并按源分组,我想知道在特定时间间隔内记录了多少具有该 ID 的事件。查询的答案可能类似于“今天,源 A 发生了 120 次事件 X,源 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
我尝试了各种多列索引(例如(事件、时间)),但没有任何改进。这似乎是一个常见的用例,我无法想象没有合理的解决方案,但我的谷歌搜索都归结为我已经拥有的查询版本,没有关于如何避免临时的特别建议(即使这样,为什么性能如此糟糕)。
有什么建议吗?
【问题讨论】: