我正在为一个跟踪使用时间的分析系统设计一个模式,并且需要查看特定日期范围内的总使用时间。
举一个简单的例子,这种查询类型将经常运行:
select sum(diff_ms) from writetest_table where time_on > ("2015-07-13 15:11:56");
在人口众多的表上,此查询通常需要7秒钟左右。它有约3500万行,运行在Amazon RDS(db.m3.xlarge)上的MySQL上的MyISAM。
摆脱WHERE子句可以使查询仅花费4秒,而添加第二个子句(time_off> XXX)则需要增加1.5秒,从而使查询时间达到8.5秒。
因为我知道通常会完成这些类型的查询,所以我想优化一些东西,使其更快,最好在5秒以下。
我从在time_on上添加索引开始,尽管它大大加快了WHERE“ =”查询,但对“>”查询没有影响。有没有一种方法可以创建可以加快WHERE“>”或“ <”查询的索引?
或者,如果还有其他建议可以查询此类查询的性能,请告诉我。
注意:我使用“ diff_ms”字段作为非规范化步骤(它等于time_off-time_on),这将聚合的性能提高了大约30%-40%。
我正在使用以下命令创建索引:
ALTER TABLE writetest_table ADD INDEX time_on (time_on) USING BTREE;
在原始查询上运行“ explain”(使用“ time_on>”)时,time_on是“ possible_key”,而select_type是“ SIMPLE”。“额外”列显示“在何处使用”,“类型”为“全部”。添加索引后,该表显示“ time_on”是“ MUL”键类型,由于同一时间可以出现两次,因此这似乎是正确的。
这是表模式:
CREATE TABLE `writetest_table` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`sessionID` int(11) DEFAULT NULL,
`time_on` timestamp NULL DEFAULT NULL,
`time_off` timestamp NULL DEFAULT NULL,
`diff_ms` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `time_on` (`time_on`)
) ENGINE=MyISAM AUTO_INCREMENT=50410902 DEFAULT CHARSET=latin1;
更新:我基于ypercube的响应创建了以下索引,但这将第一次查询的查询时间增加到大约17秒!
ALTER TABLE writetest_table ADD INDEX time_on__diff_ms__ix (time_on, diff_ms) ;
更新2:解释输出
mysql> explain select sum(diff_ms) from writetest_table where time_on > '2015-07-13 15:11:56';
+----+-------------+---------------------+-------+----------------------+----------------------+---------+------+----------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------------+-------+----------------------+----------------------+---------+------+----------+--------------------------+
| 1 | SIMPLE | writetest_table_old | index | time_on__diff_ms__ix | time_on__diff_ms__ix | 10 | NULL | 35831102 | Using where; Using index |
+----+-------------+---------------------+-------+----------------------+----------------------+---------+------+----------+--------------------------+
1 row in set (0.00 sec)
更新3:请求的查询结果
mysql> SELECT time_on FROM writetest_table ORDER BY time_on LIMIT 1;
+---------------------+
| time_on |
+---------------------+
| 2015-07-13 15:11:56 |
+---------------------+
1 row in set (0.01 sec)
SELECT COUNT(*), COUNT(diff_ms) FROM writetest_table;
writetest_table_old
” from writetest_table
。是错字还是您在不同的表中运行查询?
time_on
和diff_ms
)中是否有null ?如果添加查询会WHERE ... AND diff_ms IS NOT NULL
怎样?