我找不到像我这样的例子,所以这就是事情:
我有一个需要聚合的大数据集。
我们谈论的是〜%500M行,日期字段从2y之前到现在不等。 我的第一直觉是通过这个字段对表进行分区(在日期字段上创建一个分区),每个分区大约留下20M行。
然后我在其他字段上有索引,我将聚合/分组。
这是我的表定义(为简洁起见而简化):
create table t1(
date_field datetime not null,
additional_id int not null,
category_id int not null,
value_field1 double,
value_field2 double,
primary key(additional_id,date_field)
)
ENGINE=InnoDB
PARTITION BY RANGE(YEAR(date_field)*100 + MONTH(date_field)) (
PARTITION p_201411 VALUES LESS THAN (201411),
PARTITION p_201412 VALUES LESS THAN (201412),
#all the partitions until the current month...
PARTITION p_201610 VALUES LESS THAN (201610),
PARTITION p_201611 VALUES LESS THAN (201610),
PARTITION p_catchall VALUES LESS THAN MAXVALUE );
如果我执行直接获取日期的查询,则根据查询顶部的解释分区的输出,仅使用该月的分区:
select value_field1 where additional_id=x and date_field='2014-11-05'
但是,如果我使用日期范围(即使在同一分区内),则扫描所有分区
select value_field1 where additional_id=x and date_field> '2014-11-05' and date_field <'2014-11-10'
(如果我在两者之间使用,结果相同)。
我在这里缺少什么?这真的是分区这个表的正确方法吗?
提前致谢
答案 0 :(得分:0)
简答:不要对PARTITION BY RANGE
使用复杂的表达式。
答案很长:(除了批评BY RANGE
对范围查询的实施。)
相反,这样做:
PARTITION BY RANGE (TO_DAYS(date_field)) (
PARTITION p_201411 VALUES LESS THAN (TO_DAYS('2014-11-01')),
...
PARTITION p_catchall VALUES LESS THAN MAXVALUE ); -- unchanged
较新版本的MySQL可以使用更友好的表达式。
如果这是您的典型查询:
additional_id=x and date_field> '2014-11-05'
and date_field <'2014-11-10'
然后分区不比同等的非分区表快。您甚至可以获得非分区版本的完美索引。
另一方面,如果DROPping
旧版分区到期时为PARTITIONing
,则additional_id int
非常出色。
25个分区是好的。
附注:INT UNSIGNED
限制为20亿,所以你是溢出的1/4。 ALTER
会让你达到40亿;你可能会考虑additional_id
。 (当然,我不知道compile 'org.apache.poi:poi-ooxml:3.15'
在此表中是否是唯一的;所以也许这不是问题。)