我创建了一个MySQL表,它按日期列的月份进行分区,如下所示:
CREATE TABLE `my_big_table` (
`some_id` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`some_value` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`some_other_value` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`time` datetime NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
PARTITION BY LIST(MONTH(time))
(PARTITION p1 VALUES IN (1) ENGINE = MyISAM,
PARTITION p2 VALUES IN (2) ENGINE = MyISAM,
PARTITION p3 VALUES IN (3) ENGINE = MyISAM,
PARTITION p4 VALUES IN (4) ENGINE = MyISAM,
PARTITION p5 VALUES IN (5) ENGINE = MyISAM,
PARTITION p6 VALUES IN (6) ENGINE = MyISAM,
PARTITION p7 VALUES IN (7) ENGINE = MyISAM,
PARTITION p8 VALUES IN (8) ENGINE = MyISAM,
PARTITION p9 VALUES IN (9) ENGINE = MyISAM,
PARTITION p10 VALUES IN (10) ENGINE = MyISAM,
PARTITION p11 VALUES IN (11) ENGINE = MyISAM,
PARTITION p12 VALUES IN (12) ENGINE = MyISAM)
现在,当我跑
时explain partitions select * from my_big_table where month(time) = 2 limit 10;
我得到了输出:
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE my_big_table p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12 ALL NULL NULL NULL NULL 10762868 "Using where"
显然所有分区都在阅读,我想知道为什么。引擎是否应该足够聪明,以确定匹配值只能在分区 p2 中找到?我得到了基于日期查询的相同输出,比如
explain partitions select * from my_big_table where date(time) = '2013-02-01' limit 10;
任何线索?
干杯,亚历克斯
答案 0 :(得分:2)
除PARTITION BY RANGE
之外的所有口味都是无用的。如果您有多个值(如您所知),情况尤其如此。
相反,请考虑PARTITION BY RANGE(TO_DAYS(time))
并使用WHERE time >= '2014-02-01' AND time < '2014-02-01' + INTERVAL 7 MONTH
(作为扫描一个月的示例)。 不使用MONTH(time)
。
答案 1 :(得分:1)
好的,经过一些谷歌搜索和更多的试验和错误:
问题似乎与我的查询的where子句中的month(...)或date(...)语句有关。查询
explain partitions select * from my_big_table where time = '2013-02-01 00:00:00' limit 10;
仅按预期扫描分区 p2 。因此,只有分区列的原始值是where子句的一部分时,分区修剪似乎才有效。
干杯,亚历克斯
答案 2 :(得分:0)
您永远不应该在表值month(time) = 2
上使用函数,MySQL将始终调查此类查询的所有值(即全表扫描)。
通常,您会发现与未使用的索引相关的这种“问题”,但分区修剪也是如此。