我无法从大型MySQL表中获得合适的查询时间,目前它耗时超过20秒。问题在于GROUP BY,因为MySQL需要运行一个文件排序但是我不知道如何解决这个问题
QUERY :
SELECT play_date, COUNT(DISTINCT(email)) AS count
FROM log
WHERE type = 'play'
AND play_date BETWEEN '2009-02-23'
AND '2009-02-24'
GROUP BY play_date
ORDER BY play_date desc
EXPLAIN :
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE log ALL type,type_2 NULL NULL NULL 530892 Using where; Using filesort
表格结构
CREATE TABLE IF NOT EXISTS `log` (
`id` int(11) NOT NULL auto_increment,
`email` varchar(255) NOT NULL,
`type` enum('played','reg','friend') NOT NULL,
`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
`play_date` date NOT NULL,
`email_refer` varchar(255) NOT NULL,
`remote_addr` varchar(15) NOT NULL,
PRIMARY KEY (`id`),
KEY `email` (`email`),
KEY `type` (`type`),
KEY `email_refer` (`email_refer`),
KEY `type_2` (`type`,`timestamp`,`play_date`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=707859 ;
如果有人知道如何提高速度我会非常感激
汤姆
修改
我添加了只有play_date和类型的新索引,但MySQL拒绝使用它
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE log ALL play_date NULL NULL NULL 801647 Using where; Using filesort
此索引是使用ALTER TABLE log
ADD INDEX(type
,play_date
)创建的;
答案 0 :(得分:11)
您需要在字段type
和play_date
上创建索引。
像这样:
ALTER TABLE `log` ADD INDEX (`type`, `play_date`);
或者,或者,您可以重新排列最后一个键:
KEY `type_2` (`type`,`play_date`,`timestamp`)
所以MySQL可以使用它的左侧部分作为密钥。
答案 1 :(得分:2)
您应该在搜索的字段上添加索引。
在你的情况下,它是play_date并输入
答案 2 :(得分:1)
您没有利用名为type_2
的密钥。它是type
,timestamp
和play_date
的复合键,但您按type
和play_date
进行过滤,忽略timestamp
。因此,引擎无法使用该密钥。
您应该在字段type
和play_date
上创建索引,或从密钥timestamp
中删除type_2
。
或者您可以尝试将timestamp
合并到当前查询中作为过滤器。但从您当前的查询来看,我不认为这是合乎逻辑的。
答案 3 :(得分:0)
是否需要在play_date上设置索引,或者将复合索引中的位置移到第二位?
答案 4 :(得分:0)
最快的选择是
ALTER TABLE `log` ADD INDEX (`type`, `play_date`, 'email');
它会将此索引转换为“覆盖索引”,这意味着查询只会访问存储在内存中的索引,甚至不会转到硬盘。
答案 5 :(得分:0)
DESC参数导致MySQL不使用ORDER BY的索引。您可以将其保留为ASC并在客户端(?)反向迭代结果集。