我正在使用在 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