MySQL 100万行查询速度

时间:2009-07-16 11:20:23

标签: sql mysql performance

我无法从大型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(typeplay_date)创建的;

6 个答案:

答案 0 :(得分:11)

您需要在字段typeplay_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的密钥。它是typetimestampplay_date的复合键,但您按typeplay_date进行过滤,忽略timestamp。因此,引擎无法使用该密钥。

您应该在字段typeplay_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并在客户端(?)反向迭代结果集。