我有一个表格,我按月在DATE列上进行分区。我还在同一列上添加了一个索引:
CREATE TABLE `report_aggregate` (
`bus_date` date NOT NULL,
`col01` int(10) NOT NULL,
`col02` varchar(25) DEFAULT NULL
)
ENGINE=InnoDB DEFAULT CHARSET=utf8
PARTITION BY RANGE( TO_DAYS(bus_date) ) (
PARTITION lt201001 VALUES LESS THAN( TO_DAYS('2010-01-01 00:00:00') ),
PARTITION lt201201 VALUES LESS THAN( TO_DAYS('2012-01-01 00:00:00') ),
...
PARTITION lt201501 VALUES LESS THAN( TO_DAYS('2015-01-01 00:00:00') ),
PARTITION ltMAX VALUES LESS THAN MAXVALUE
);
ALTER TABLE report_aggregate ADD INDEX('bus_date');
现在,当我使用指定的单个日期进行查询时,它使用索引:
SELECT * FROM report_aggregate WHERE bus_date ='2014-09-01';
+----+-------------+--------------------+------------+------+---------------+----------+---------+-------+-------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------------+------+---------------+----------+---------+-------+-------+-------+
| 1 | SIMPLE | report_aggregate | lt201410 | ref | bus_date | bus_date | 3 | const | 59728 | NULL |
+----+-------------+--------------------+------------+------+---------------+----------+---------+-------+-------+-------+
如果我在两天内进行查询,它还会使用索引:
SELECT * FROM report_aggregate WHERE bus_date> ='2014-09-01'AND bus_date< =''2014-09-02';
+----+-------------+--------------------+------------+-------+---------------+----------+---------+------+--------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------------+-------+---------------+----------+---------+------+--------+-------------+
| 1 | SIMPLE | report_aggregate | lt201410 | range | bus_date | bus_date | 3 | NULL | 123232 | Using where |
+----+-------------+--------------------+------------+-------+---------------+----------+---------+------+--------+-------------+
SELECT * FROM report_aggregate
WHERE bus_date IN('2014-09-01','2014-09-10');
+----+-------------+--------------------+------------+-------+---------------+----------+---------+------+--------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------------+-------+---------------+----------+---------+------+--------+-------------+
| 1 | SIMPLE | report_aggregate | lt201410 | range | bus_date | bus_date | 3 | NULL | 120302 | Using where |
+----+-------------+--------------------+------------+-------+---------------+----------+---------+------+--------+-------------+
如果我在3天或更长时间内进行查询,则不会使用索引:
SELECT * FROM report_aggregate WHERE bus_date> ='2014-09-01'AND bus_date< =''2014-09-03';
+----+-------------+--------------------+------------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | report_aggregate | lt201410 | ALL | bus_date | NULL | NULL | NULL | 751901 | Using where |
+----+-------------+--------------------+------------+------+---------------+------+---------+------+--------+-------------+
如果日期范围是连续的并不重要,只要查询过滤3个或更多唯一日期,您就可以使用> = with< =,IN()或BETWEEN ...它不再使用索引。 防爆。 SELECT * FROM report_aggregate WHERE bus_date IN('2014-09-01','2014-09-10','2014-09-15');
+----+-------------+--------------------+------------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | report_aggregate | lt201410 | ALL | bus_date | NULL | NULL | NULL | 751901 | Using where |
+----+-------------+--------------------+------------+------+---------------+------+---------+------+--------+-------------+
另请注意,它不跨越多个分区,并且EXPLAIN PARTITIONS始终报告正在使用一个分区(lt201410)。我之所以提到这一点,是因为我曾经认为它可能无法跨分区使用索引,但由于它只使用一个分区,因此已被排除。
知道为什么它不使用包含在过滤器中的超过2个日期的索引?