MySQL 100万行查询速度
Posted
技术标签:
【中文标题】MySQL 100万行查询速度【英文标题】:MySQL 1 millon row query speed 【发布时间】:2009-07-16 11:20:22 【问题描述】:我无法从大型 mysql 表中获得合适的查询时间,目前它需要 20 多秒。问题在于 GROUP BY,因为 MySQL 需要运行文件排序,但我不知道如何解决这个问题
查询:
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
解释:
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 和 type 添加了新索引,但 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
) 创建的;
【问题讨论】:
请在(type, play_date)
上发布您是如何创建索引的
ALTER TABLE log
ADD INDEX (type
, play_date
);
【参考方案1】:
您需要在字段type
AND play_date
上创建索引。
像这样:
ALTER TABLE `log` ADD INDEX (`type`, `play_date`);
或者,您也可以像这样重新排列最后一个键:
KEY `type_2` (`type`,`play_date`,`timestamp`)
因此 MySQL 可以将其左侧部分用作键。
【讨论】:
我已经尝试添加该键,但 MySQL 拒绝使用它,它将其声明为可能的索引,但随后在不使用任何索引的情况下运行查询 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE log ALL play_date NULL NULL NULL 801647 使用 where;使用文件排序【参考方案2】:您应该在搜索所依据的字段上添加索引。
在你的情况下它 play_date 和类型
【讨论】:
【参考方案3】:您没有利用名为type_2
的密钥。它是type
、timestamp
和play_date
的复合键,但您正在过滤type
和play_date
,忽略timestamp
。因此,引擎无法使用该密钥。
您应该在字段type
和play_date
上创建索引,或者从键type_2
中删除timestamp
。
或者您可以尝试将timestamp
合并到您当前的查询中作为过滤器。但从您当前的查询来看,我认为这不合逻辑。
【讨论】:
【参考方案4】:play_date上是否需要有索引,或者将复合索引中的位置移到第二位?
【讨论】:
【参考方案5】:最快的选择是这个
ALTER TABLE `log` ADD INDEX (`type`, `play_date`, 'email');
它将这个索引变成一个“覆盖索引”,这意味着查询只会访问存储在内存中的索引,甚至不会进入硬盘。
【讨论】:
【参考方案6】:DESC 参数导致 MySQL 不使用 ORDER BY 的索引。您可以将其保留为 ASC 并在客户端反向迭代结果集 (?)。
【讨论】:
以上是关于MySQL 100万行查询速度的主要内容,如果未能解决你的问题,请参考以下文章
具有 10+ 百万行的 MySQL 表 - 如何使用索引加快搜索速度?
MYSQL 从具有 100 万行的表中选择 distinct(indexed_column)