2013-08-18 62 views
6

我有表作为MySQL索引的范围

+-------------------+----------------+------+-----+---------------------+-----------------------------+ 
| Field    | Type   | Null | Key | Default    | Extra      | 
+-------------------+----------------+------+-----+---------------------+-----------------------------+ 
| id    | bigint(20)  | NO | PRI | NULL    | auto_increment    | 
| runtime_id  | bigint(20)  | NO | MUL | NULL    |        | 
| place_id   | bigint(20)  | NO | MUL | NULL    |        | 
| amended_timestamp | varchar(50) | YES |  | NULL    |        | 
| applicable_at  | timestamp  | NO |  | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | 
| schedule_time  | timestamp  | NO | MUL | 0000-00-00 00:00:00 |        | 
| quality_indicator | varchar(10) | NO |  | NULL    |        | 
| flow_rate   | decimal(15,10) | NO |  | NULL    |        | 
+-------------------+----------------+------+-----+---------------------+-----------------------------+ 

我对schedule_time有指数

create index table_index on table(schedule_time asc); 

表目前有2121552+记录。

我不明白的事情是,当我做解释

explain select runtime_id from table where schedule_time >= now() - INTERVAL 1 DAY; 
+----+-------------+----------+-------+------------------------------+------------------------------+---------+------+-------+-------------+ 
| id | select_type | table | type | possible_keys    | key       | key_len | ref | rows | Extra  | 
+----+-------------+----------+-------+------------------------------+------------------------------+---------+------+-------+-------------+ 
| 1 | SIMPLE  | table | range | table_index     | table_index     | 4  | NULL | 38088 | Using where | 
+----+-------------+----------+-------+------------------------------+------------------------------+---------+------+-------+-------------+ 
1 row in set (0.00 sec) 

上述指标被使用,但下面的一个没有。

mysql> explain select runtime_id from table where schedule_time >= now() - INTERVAL 30 DAY; 
+----+-------------+----------+------+------------------------------+------+---------+------+---------+-------------+ 
| id | select_type | table | type | possible_keys    | key | key_len | ref | rows | Extra  | 
+----+-------------+----------+------+------------------------------+------+---------+------+---------+-------------+ 
| 1 | SIMPLE  | table | ALL | table_index     | NULL | NULL | NULL | 2118107 | Using where | 
+----+-------------+----------+------+------------------------------+------+---------+------+---------+-------------+ 
1 row in set (0.00 sec) 

,我会很感激,如果有人可以什么错在这里指出的数据是每12分钟更新一次,并随着时间的推移通过查询30天,也可以是60天变得非常缓慢。

,我打算使用它是如下

select avg(flow_rate),c.group from table a ,(select runtime_id from table where schedule_time >= now() - INTERVAL 1 DAY group by schedule_time) b,place c where a.runtime_id = b.runtime_id and a.place_id = c.id group by c.group; 

更新=====>

按照也会失败之间的意见最后的查询。

mysql> explain select runtime_id from table where schedule_time between '2013-07-17 12:48:00' and '2013-08-17 12:48:00'; 
+----+-------------+----------+------+------------------------------+------+---------+------+---------+-------------+ 
| id | select_type | table | type | possible_keys    | key | key_len | ref | rows | Extra  | 
+----+-------------+----------+------+------------------------------+------+---------+------+---------+-------------+ 
| 1 | SIMPLE  | table | ALL | table_index     | NULL | NULL | NULL | 2118431 | Using where | 
+----+-------------+----------+------+------------------------------+------+---------+------+---------+-------------+ 
1 row in set (0.00 sec) 

mysql> explain select runtime_id from table where schedule_time between '2013-08-16 12:48:00' and '2013-08-17 12:48:00'; 
+----+-------------+----------+-------+------------------------------+------------------------------+---------+------+-------+-------------+ 
| id | select_type | table | type | possible_keys    | key       | key_len | ref | rows | Extra  | 
+----+-------------+----------+-------+------------------------------+------------------------------+---------+------+-------+-------------+ 
| 1 | SIMPLE  | table | range | table_index     | table_index     | 4  | NULL | 38770 | Using where | 
+----+-------------+----------+-------+------------------------------+------------------------------+---------+------+-------+-------------+ 
1 row in set (0.00 sec) 

更新2 =======>

mysql> select count(*) from table where schedule_time between '2013-08-16 12:48:00' and '2013-08-17 12:48:00'; 
+----------+ 
| count(*) | 
+----------+ 
| 19440 | 
+----------+ 
1 row in set (0.01 sec) 

mysql> select count(*) from table where schedule_time between '2013-07-17 12:48:00' and '2013-08-17 12:48:00'; 
+----------+ 
| count(*) | 
+----------+ 
| 597132 | 
+----------+ 
1 row in set (0.00 sec) 

Server版本:5.5.24-0ubuntu0.12.04.1(Ubuntu的)

+0

类似的问题在这里 - 这个想法是使用'之间'的声明:http://stackoverflow.com/questions/2041575/mysql-query-records-between-today-and-last-30-days – FreudianSlip

+1

我wasn能够重现这种行为(不要试图这么做,认为...)只是一个疯狂的猜测:运行'ANALYZE TABLE my_table'会改善吗? –

+0

@SylvainLeroux我跑了ANALYZE TABLE,但是两者之间和Interval之间的结果相同 –

回答

3

MySQL优化试图做最快的事情 - 它认为使用索引需要比进行表扫描所需的时间长或长,它会放弃可用的索引。这就是你看到它在你的例子中做的事情:如果范围很小(1天),索引将会更快;在范围很大的情况下,你会碰到更多的表,你可能会直接扫描表(记住,使用索引包括搜索索引,然后从表中获取索引记录 - 两组寻求)。

如果您认为自己比优化程序更好(它不完美),请使用提示(http://dev.mysql.com/doc/refman/5.5/en/index-hints.html)。