MySQL分区日期范围索引行为

时间:2014-09-30 18:40:29

标签: mysql indexing partition

我有一个表格,我按月在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个日期的索引?

0 个答案:

没有答案