【问题标题】:Mysql partitioning: Partitions outside of date range is includedMysql 分区:包括日期范围之外的分区
【发布时间】:2011-06-21 08:31:50
【问题描述】:

我刚刚尝试配置基于日期的分区,但似乎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   |       |
+----+-------------+------------+------------+------+---------------+------+---------+-------+------+-------+

【问题讨论】:

    标签: mysql database-partitioning


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

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

      在mysql中对日期进行分区很困难,并且在分区实现中存在很多缺点,至少如果你想覆盖很多不同的查询约束,我们通常会在表中放置一个整数id,指向日历而不是一个 DATE 类型,因为我们发现 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 ,不应该用于查询,它只是方便脚本自动创建新/删除旧分区。

      【讨论】:

        猜你喜欢
        • 2012-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-03
        • 1970-01-01
        • 1970-01-01
        • 2012-08-06
        相关资源
        最近更新 更多