【问题标题】:Convert to a Partitioned Table转换为分区表
【发布时间】:2011-08-19 22:57:22
【问题描述】:

我有以下表结构,其中包含实时数据:

 CREATE TABLE IF NOT EXISTS `userstatistics` (
   `user_id` int(10) unsigned NOT NULL,
   `number_logons` int(7) unsigned NOT NULL DEFAULT '0',
   `number_profileminiviews` int(7) unsigned NOT NULL DEFAULT '0',
   `number_profilefullviews` int(7) unsigned NOT NULL DEFAULT '0',
   `number_mailsreceived` int(7) unsigned NOT NULL DEFAULT '0',
   `number_interestreceived` int(7) unsigned NOT NULL DEFAULT '0',
   `number_favouratesreceived` int(7) unsigned NOT NULL DEFAULT '0',
   `number_friendshiprequestreceived` int(7) unsigned NOT NULL DEFAULT '0',
   `number_imchatrequestreceived` int(7) unsigned NOT NULL DEFAULT '0',
   `yearweek` int(6) unsigned NOT NULL DEFAULT '0',
   PRIMARY KEY (`user_id`,`yearweek`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

我想将其转换为具有以下结构的分区表:

 CREATE TABLE IF NOT EXISTS `userstatistics` (
   `user_id` int(10) unsigned NOT NULL,
   `number_logons` int(7) unsigned NOT NULL DEFAULT '0',
   `number_profileminiviews` int(7) unsigned NOT NULL DEFAULT '0',
   `number_profilefullviews` int(7) unsigned NOT NULL DEFAULT '0',
   `number_mailsreceived` int(7) unsigned NOT NULL DEFAULT '0',
   `number_interestreceived` int(7) unsigned NOT NULL DEFAULT '0',
   `number_favouratesreceived` int(7) unsigned NOT NULL DEFAULT '0',
   `number_friendshiprequestreceived` int(7) unsigned NOT NULL DEFAULT '0',
   `number_imchatrequestreceived` int(7) unsigned NOT NULL DEFAULT '0',
   `yearweek` int(6) unsigned NOT NULL DEFAULT '0',
   PRIMARY KEY (`user_id`,`yearweek`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
 /*!50100 PARTITION BY RANGE (yearweek)
 (PARTITION userstats_201108 VALUES LESS THAN (201108) ENGINE = InnoDB,
  PARTITION userstats_201109 VALUES LESS THAN (201109) ENGINE = InnoDB,
  PARTITION userstats_201110 VALUES LESS THAN (201110) ENGINE = InnoDB,
  PARTITION userstats_201111 VALUES LESS THAN (201111) ENGINE = InnoDB,
  PARTITION userstats_201112 VALUES LESS THAN (201112) ENGINE = InnoDB,
  PARTITION userstats_201113 VALUES LESS THAN (201113) ENGINE = InnoDB,
  PARTITION userstats_201114 VALUES LESS THAN (201114) ENGINE = InnoDB,
  PARTITION userstats_201115 VALUES LESS THAN (201115) ENGINE = InnoDB,
  PARTITION userstats_201116 VALUES LESS THAN (201116) ENGINE = InnoDB,
  PARTITION userstats_201117 VALUES LESS THAN (201117) ENGINE = InnoDB,
  PARTITION userstats_201118 VALUES LESS THAN (201118) ENGINE = InnoDB,
  PARTITION userstats_201119 VALUES LESS THAN (201119) ENGINE = InnoDB,
  PARTITION userstats_201120 VALUES LESS THAN (201120) ENGINE = InnoDB,
  PARTITION userstats_201121 VALUES LESS THAN (201121) ENGINE = InnoDB,
  PARTITION userstats_max VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */;

我该如何进行这种转换?

只需将第二条SQL语句的第一行改为

 ALTER TABLE 'userstatistics' (

这样可以吗?

从 MySQL 5.0 升级到 5.1。

【问题讨论】:

    标签: mysql database-partitioning


    【解决方案1】:

    首先,您需要运行 MySQL 5.1 或更高版本。 MySQL 5.0 不支持分区。

    其次,请注意单引号(分隔字符串和日期)和反引号(分隔 MySQL 中的表和列标识符)之间的区别。在适当的地方使用正确的类型。我提到这一点,因为您的示例使用了错误的引号类型:

    ALTER TABLE 'userstatistics' (
    

    应该是:

    ALTER TABLE `userstatistics` (
    

    最后,是的,您可以使用 ALTER TABLE 将表重组为分区。这是我在 MySQL 5.1.57 上测试的语句的精确复制和粘贴:

    ALTER TABLE userstatistics PARTITION BY RANGE (yearweek)  (
    PARTITION userstats_201108 VALUES LESS THAN (201108) ENGINE = InnoDB,   
    PARTITION userstats_201109 VALUES LESS THAN (201109) ENGINE = InnoDB,   
    PARTITION userstats_201110 VALUES LESS THAN (201110) ENGINE = InnoDB,   
    PARTITION userstats_201111 VALUES LESS THAN (201111) ENGINE = InnoDB,   
    PARTITION userstats_201112 VALUES LESS THAN (201112) ENGINE = InnoDB,   
    PARTITION userstats_201113 VALUES LESS THAN (201113) ENGINE = InnoDB,   
    PARTITION userstats_201114 VALUES LESS THAN (201114) ENGINE = InnoDB,   
    PARTITION userstats_201115 VALUES LESS THAN (201115) ENGINE = InnoDB,   
    PARTITION userstats_201116 VALUES LESS THAN (201116) ENGINE = InnoDB,   
    PARTITION userstats_201117 VALUES LESS THAN (201117) ENGINE = InnoDB,   
    PARTITION userstats_201118 VALUES LESS THAN (201118) ENGINE = InnoDB,   
    PARTITION userstats_201119 VALUES LESS THAN (201119) ENGINE = InnoDB,   
    PARTITION userstats_201120 VALUES LESS THAN (201120) ENGINE = InnoDB,   
    PARTITION userstats_201121 VALUES LESS THAN (201121) ENGINE = InnoDB, 
    PARTITION userstats_max VALUES LESS THAN MAXVALUE ENGINE = InnoDB);
    

    请注意,这会导致表重组,因此如果此表中已有大量数据,则运行需要一段时间。确切的时间取决于您拥有多少数据,以及您的硬件速度和其他因素。请注意,在重组表时,它会被锁定并且无法被其他查询读取和写入。

    【讨论】:

    • Bill 的分步文档肯定比帮助菜单好。 :-) 而且这个分区假设您将在一个月内进行更多范围查询。
    • Percona Toolkit's pt-online-schema-change 声称能够对在线 MySQL 表进行分区没有基于表重组的阻塞ref two
    • @ijoseph,我在一家公司工作,pt-online-schema-change 每天要使用几十次,所以我很了解。你是对的,它复制数据而不会一直锁定表。但事实上,在将任何数据复制到该表之前,它确实对新表执行了 ALTER TABLE。它执行相同类型的锁定,只是持续时间很短。
    • 哇,看看你的证书,我发现你也在 Percona 工作过。
    • 啊,好吧,那么从技术上讲,pt-online-schema-change 确实 锁定了。但是,该锁定不会阻止读取访问,因为它是在从该表读取数据之前在新表上完成的,对吗?它会阻止写访问吗?
    【解决方案2】:

    看这个 http://dev.mysql.com/doc/refman/5.1/en/alter-table.html 关于变更表。

    然后特别是alter table。

    ADD/DROP/COALESCE/REORGANIZE 分区sql提供了几乎所有的功能来管理你的分区。

    注意哈希只能用于整数。

    ALTER TABLE ... ADD PARTITION 不会创建临时表,除非与 NDB 表一起使用。 RANGE 或 LIST 分区的 ADD 或 DROP 操作是立即操作或几乎是立即操作。 HASH 或 KEY 分区的 ADD 或 COALESCE 操作在更改的分区之间复制数据;除非使用 LINEAR HASH 或 LINEAR KEY,否则这与创建新表非常相似(尽管操作是逐个分区完成的)。 REORGANIZE 操作仅复制更改的分区,不触及未更改的分区。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-11
      • 2021-11-03
      • 1970-01-01
      • 2010-11-18
      相关资源
      最近更新 更多