MySQL表索引优化

时间:2012-04-13 08:12:12

标签: mysql optimization amazon-rds

我正在使用在Amazon RDS上拥有MySQL数据库的应用程序。问题表格如下:

CREATE TABLE `log` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `timestamp` datetime NOT NULL,
  `username` varchar(45) NOT NULL,
  .. snip some varchar and int fields ..
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

这个系统已经测试了一段时间,数据集已经非常庞大,查询开始变得很慢。

SELECT COUNT(*) FROM log --> 16307224 (takes 105 seconds to complete)

这个表几乎只用于构建一个像这样的查询的报告

SELECT timestamp, username, [a few more] FROM log 
WHERE timestamp  BETWEEN '2012-03-30 08:00:00' AND '2012-03-30 16:00:00' 
AND username='XX' 

这通常会在1000到6000行之间产生约100-180秒的时间来完成,这意味着Web应用程序通常会超时并留下空报告(我也会查看超时,但这个问题是为根本原因)。

我对数据库不是很了解,但我的猜测是在这里杀死我的是BETWEEN。我在想的是我应该以某种方式使用时间戳作为索引。使用用户名的时间戳仍然应该提供唯一性(我不会将id字段用于任何内容)。

如果有人在那里提出优化建议,我会全力以赴。

更新:

表格现在改为以下

CREATE TABLE `log` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `timestamp` datetime NOT NULL,
  `username` varchar(45) NOT NULL,
  .. snip ..
  `task_id` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `index_un_ts` (`timestamp`,`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
EXPLAIN语句的

SELECT返回以下内容

id => 1
select_type => SIMPLE
table => log
type => range
possible_keys => index_un_ts
key => index_un_ts
key_len => 55
ref => 
rows => 52258
Extra => Using where; Using index

1 个答案:

答案 0 :(得分:1)

时间戳列和userid上的索引会很有帮助。您需要能够读取EXPLAIN语句的输出。

转到MySQL并执行以下操作:

EXPLAIN SELECT timestamp, username, [a few more] FROM log 
WHERE timestamp  BETWEEN '2012-03-30 08:00:00' AND '2012-03-30 16:00:00' 
AND username='XX' 

这将向您展示MySQL用于执行查询的计划。将有一个名为key的列。这表明MySQL在查询中使用了什么索引。我怀疑你会看到所有那里意味着MySQL正在从上到下扫描表格,与你的where子句匹配每一行。现在,在timestamp和userid列上创建索引。再次运行EXPLAIN语句。您应该看到在密钥列中创建的索引。

如果MySQL使用索引,那么您的查询应该快得多。记住不要过度索引。索引使插入,更新和删除更慢。向表中插入新行并且表上有三个索引时,新行必须将3个值写入三个不同的索引。所以这是一把双刃剑。