时间戳列上的MySQL索引不用于大日期范围

bab*_*ira 7 mysql optimization

我有桌子

+-------------------+----------------+------+-----+---------------------+-----------------------------+
| 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                |                             |
+-------------------+----------------+------+-----+---------------------+-----------------------------+
Run Code Online (Sandbox Code Playgroud)

我的schedule_time索引为

create index table_index on table(schedule_time asc);
Run Code Online (Sandbox Code Playgroud)

该表目前有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)
Run Code Online (Sandbox Code Playgroud)

使用上面的索引,但下面没有.

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)
Run Code Online (Sandbox Code Playgroud)

我会很感激,如果有人可以什么错在这里指出,由于数据每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;
Run Code Online (Sandbox Code Playgroud)

更新=====>

根据之间的评论也失败了.

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)
Run Code Online (Sandbox Code Playgroud)

更新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)
Run Code Online (Sandbox Code Playgroud)

服务器版本:5.5.24-0ubuntu0.12.04.1(Ubuntu)

D M*_*Mac 5

MySQL 优化器尝试做最快的事情。如果它认为使用索引将花费与表扫描一样长或更长的时间,它就会放弃可用的索引。

这就是您在示例中看到的操作:

  • 如果范围很小(1 天),索引会更快;
  • 在范围很大的地方,您将访问更多的表,您最好直接扫描表(请记住,使用索引涉及搜索索引,然后从表中获取索引记录 - 两组寻求)。

如果您认为您比优化器更了解(它并不完美),请使用 INDEX 提示

USE INDEX (index_list) 提示告诉 MySQL 仅使用命名索引之一来查找表中的行。替代语法 IGNORE INDEX (index_list) 告诉 MySQL 不要使用某些特定的索引或索引。如果 EXPLAIN 显示 MySQL 使用了可能索引列表中的错误索引,这些提示很有用。