1

我刚刚尝试根据日期配置分区,但似乎mysql仍然包含一个没有相关数据的分区。它将使用相关分区,但由于某种原因还包括最旧的分区。我做错了吗?

版本是 5.1.44 (MyISAM)

我首先添加了一些基于“day”的分区,它的类型是“date”

ALTER TABLE ptest
PARTITION BY RANGE(TO_DAYS(day))
(
PARTITION p1 VALUES LESS THAN (TO_DAYS('2009-08-01')),
PARTITION p2 VALUES LESS THAN (TO_DAYS('2009-11-01')),
PARTITION p3 VALUES LESS THAN (TO_DAYS('2010-02-01')),
PARTITION p4 VALUES LESS THAN (TO_DAYS('2010-05-01'))
);

查询后,我发现它使用“旧”分区,不应该包含任何相关数据。

mysql> explain partitions select * from ptest where day between '2010-03-11' and '2010-03-12';
+----+-------------+------------+------------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table      | partitions | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+------------+------------+-------+---------------+------+---------+------+------+-------------+
| 1  | SIMPLE      | ptest      | p1,p4      | range | day           | day  | 3       | NULL | 79   | Using where |
+----+-------------+------------+------------+-------+---------------+------+---------+------+------+-------------+

当我选择一天时,它按预期工作:

mysql> explain partitions select * from ptest where day = '2010-03-11';
+----+-------------+------------+------------+------+---------------+------+---------+-------+------+-------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref   | rows | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+-------+------+-------+
| 1  | SIMPLE      | ptest      | p4         | ref  | day           | day  | 3       | const | 39   |       |
+----+-------------+------------+------------+------+---------------+------+---------+-------+------+-------+
4

2 回答 2

2

这实际上是预期的结果,因为最旧的分区将始终保存未计算为有效日期(空)的值。解决此问题的方法是创建一个额外的分区,该分区将不保存任何数据,并且在最早日期之前存在所有值。此分区将始终被扫描,但对性能影响不大,因为它是空的。

http://bugs.mysql.com/bug.php?id=49754

于 2011-06-21T00:31:50.420 回答
1

您已在 TO_DAYS(date) 上进行了分区,这意味着分区修剪通常只会在简单的情况下发生,除非您在约束上应用 TO_DAYS(date)。

你必须做例如 select * from ptest where day between TO_DAYS('2010-03-11') 和 TO_DAYS('2010-03-12') - 尽管在这种情况下它可能是mysql之间的缺点。

在mysql中对日期进行分区很困难,并且在分区实现中存在很多缺点,至少如果你想涵盖很多不同的查询约束,我们通常会在指向日历而不是DATE类型的表中放置一个整数id ,因为我们发现 mysql 处理简单整数上的分区与涉及函数(例如 TO_DAYS)的列上的分区相比非常可靠,我们有

create table datatbl (
  time_id int NOT NULL,
  ....
);

time_id 引用了一个预填了未来 10 年日期的日历,看起来像

create table calendar (
  time_id int primary key
  year int NOT NULL,
  month int NOT NULL,
  day int NOT NULL,
  dayofyear int NOT NULL,
  quarter int NOT NULL,
  is_weekend char(1) NOT NULL,
  db_date DATE not NULL,
  unique index(year,month,day),
  unique index(dbdate)
);

查询连接到该表,因此获取一个月的所有数据只需要一个where cal.year = 2010 and cal.month = 1. 或者可以这样做cal.db_date between '2010-01-01' and '2010-01-31'

datatbl在 time_id 上进行分区,上述查询将使 mysql 进行分区修剪。time_id 也是年/月/日的组合,因此 2010-03-03 的 time_id 将是整数 20100303 ,不应该用于查询,它只是方便脚本自动创建新/删除旧分区。

于 2010-03-19T10:19:44.850 回答