【问题标题】:Adding a partition to already partitioned table向已分区的表添加分区
【发布时间】:2018-03-22 20:20:53
【问题描述】:

向已经分区的表添加另一个分区的最佳方法是什么?

原始的CREATE TABLE 语句如下所示:

CREATE TABLE `command_log` (
  `id` bigint(20) NOT NULL,
  `insert_time` datetime NOT NULL,
  `start_time` timestamp NULL DEFAULT '0000-00-00 00:00:00',
  `end_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `command` varchar(255) NOT NULL,
  `parameters` varchar(255) DEFAULT NULL,
  `result` mediumblob,
  `status` int(11) NOT NULL,
  PRIMARY KEY (`id`,`insert_time`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (to_days(insert_time))
(PARTITION p001 VALUES LESS THAN (736237) ENGINE = InnoDB,
 PARTITION p002 VALUES LESS THAN (736268) ENGINE = InnoDB,
 PARTITION p003 VALUES LESS THAN (736298) ENGINE = InnoDB,
 ...
 PARTITION p064 VALUES LESS THAN (738156) ENGINE = InnoDB,
 PARTITION p065 VALUES LESS THAN (738187) ENGINE = InnoDB,
 PARTITION p066 VALUES LESS THAN (738215) ENGINE = InnoDB,
 PARTITION p067 VALUES LESS THAN MAXVALUE ENGINE = InnoDB)

假设我只想添加 1 个额外的分区,在本例中为 p067。这是否需要完整的ALTER TABLE 语句,例如:

ALTER TABLE command_log 
PARTITION by range (to_days(insert_time))
(
    partition p059 VALUES LESS THAN (to_days('2020-08-01'))
  , partition p060 VALUES LESS THAN (to_days('2020-09-01'))
  , partition p061 VALUES LESS THAN (to_days('2020-10-01'))
  , partition p062 VALUES LESS THAN (to_days('2020-11-01'))
  , partition p063 VALUES LESS THAN (to_days('2020-12-01'))
  , partition p064 VALUES LESS THAN (to_days('2021-01-01'))
  , partition p065 VALUES LESS THAN (to_days('2021-02-01'))
  , partition p066 VALUES LESS THAN (to_days('2021-03-01'))
  , partition p067 VALUES LESS THAN (to_days('2021-04-01'))
  , partition p068 VALUES LESS THAN (MAXVALUE)
);

如果是这样,究竟会发生什么?

我未包含在此语句中的旧分区是否会被删除(例如 p001 - p058)?

这样做是否会清除表中的任何现有数据(例如 p059 中的数据)?

谢谢!

【问题讨论】:

    标签: mysql database-partitioning


    【解决方案1】:

    您不必重新定义所有早期的分区。

    范围分区表中的常见操作是将处理小于 MAXVALUE 的值的最后一个分区拆分为特定范围的几个新分区。您可以使用 REORGANIZE PARTITION 来做到这一点。

    例如,要将最后一个分区拆分为两个固定日期范围的新分区,最后加上一个新的 maxvalue 分区:

    ALTER TABLE command_log REORGANIZE PARTITION p067 INTO (
      partition p067 VALUES LESS THAN (TO_DAYS('2021-04-01'))
    , partition p068 VALUES LESS THAN (TO_DAYS('2021-05-01'))
    , partition p069 VALUES LESS THAN (MAXVALUE)
    );
    

    所有较早的分区都不会受到此重组操作的影响。

    如果您在最后一个分区仍为空(即它包含零行)时执行此重组,则不需要复制数据,并且操作应该几乎是即时的。

    如果您忘记进行重组,并且最后一个分区收集了 一些 行,那么重组还为时不晚 - 但需要一点时间,与数量成正比您拆分的分区中的行。重组包含数据的分区确实需要复制数据行,但只需要复制您正在重组的分区的行。早期的分区仍然保持不变。

    更多详情请见https://dev.mysql.com/doc/refman/5.7/en/partitioning-management-range-list.html

    【讨论】:

      【解决方案2】:

      我在 Mysql 8 中为 最初没有任何分区的现有表动态创建分区时遇到同样的问题。

      我必须为未来的日期添加分区并不断添加。

      解决此问题的步骤:

      1. 获取最新的分区名称(创建包含日期的分区名称)

      2. 如果分区日期日期不存在,则使用“范围”基本机制创建分区。 查询就像创建分区:

        ALTER TABLE <tableName> PARTITION BY RANGE (TO_DAYS(<columnName>)) (
        PARTITION p20200527 VALUES LESS THAN (TO_DAYS('2020-05-28')),  
        PARTITION p20200528 VALUES LESS THAN (TO_DAYS('2020-05-29')),  
        PARTITION p20200529 VALUES LESS THAN (TO_DAYS('2020-05-30')),  
        PARTITION p20200530 VALUES LESS THAN MAXVALUE);
        
      3. 一旦我们在表上有分区,我们就必须使用“重组”来添加分区。

        ALTER TABLE <tableName> REORGANIZE PARTITION p20200730 INTO ( 
        PARTITION p20200530 VALUES LESS THAN (TO_DAYS('2020-05-31')),  
        PARTITION p20200531 VALUES LESS THAN (TO_DAYS('2020-06-01')),  
        PARTITION p20200601 VALUES LESS THAN (TO_DAYS('2020-06-02')),  
        PARTITION p20200602 VALUES LESS THAN MAXVALUE);
        

      底线是: 如果您的表上没有任何分区并且想在任何日期列上添加它,您可以随时添加它。一旦您使用基于“范围”的机制在日期上对表进行了分区,并且您想要添加更多分区,然后使用“重组”添加这些分区。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-30
        • 2022-07-28
        • 1970-01-01
        • 2014-12-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多