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

您应该在字段typeplay_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万行查询速度的主要内容,如果未能解决你的问题,请参考以下文章

AWS RDS 大型实例上的 MySQL 全文搜索速度极慢

具有 10+ 百万行的 MySQL 表 - 如何使用索引加快搜索速度?

MYSQL 从具有 100 万行的表中选择 distinct(indexed_column)

中 MySQL 表的慢查询(100 万行)

假如mysql数据库单表有100W行记录,有哪些方式加快查询速度

一个数据库的查询速度很慢,但在他的副本上查询速度很快