分区表可以解决按月和按id物理分表引起的表数量过多的问题,提供一定的查询便利,使用过程中需要遵循一些约定,以避免查询扩散到所有分区。

分区表的创建
[code type=sql]
CREATE TABLE IF NOT EXISTS `book_followed_login_user2` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`ym` int(6) unsigned NOT NULL DEFAULT ‘0’,
`time` datetime NOT NULL DEFAULT ‘0000-00-00 00:00:00’,
`book` int(11) unsigned NOT NULL DEFAULT ‘0’,
`user` int(11) unsigned NOT NULL DEFAULT ‘0’,
PRIMARY KEY (`id`,`ym`),
KEY `id` (`id`),
KEY `ym` (`ym`),
KEY `time` (`time`),
KEY `book` (`book`),
KEY `user` (`user`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1
PARTITION BY RANGE (`ym`)
(PARTITION ppast VALUES LESS THAN (201511) ENGINE = InnoDB,
PARTITION p201511 VALUES LESS THAN (201512) ENGINE = InnoDB,
PARTITION p201512 VALUES LESS THAN (201601) ENGINE = InnoDB,
PARTITION p201601 VALUES LESS THAN (201602) ENGINE = InnoDB,
PARTITION p201602 VALUES LESS THAN (201603) ENGINE = InnoDB,
PARTITION p201603 VALUES LESS THAN (201604) ENGINE = InnoDB,
PARTITION p201604 VALUES LESS THAN (201605) ENGINE = InnoDB,
PARTITION p201605 VALUES LESS THAN (201606) ENGINE = InnoDB,
PARTITION p201606 VALUES LESS THAN (201607) ENGINE = InnoDB,
PARTITION p201607 VALUES LESS THAN (201608) ENGINE = InnoDB,
PARTITION p201608 VALUES LESS THAN (201609) ENGINE = InnoDB,
PARTITION p201609 VALUES LESS THAN (201610) ENGINE = InnoDB,
PARTITION p201610 VALUES LESS THAN (201611) ENGINE = InnoDB,
PARTITION p201611 VALUES LESS THAN (201612) ENGINE = InnoDB,
PARTITION p201612 VALUES LESS THAN (201701) ENGINE = InnoDB,
PARTITION pfuture VALUES LESS THAN MAXVALUE ENGINE = InnoDB) ;
[/code]
以上注意:
1、 一个流水号自增id;
2、 ym是time的冗余字段,存放月份数据,格式是201512。用于分区PARTITION BY RANGE(`ym`),虽然可以通过运算得到,但是冗余存放一个int型的值便于按分区检索;
3、 PRIMARY KEY以id和ym联合组成;
4、 分区包含一个ppast和pfuture的分区,用来容纳异常的数值,一般按月建好所需分区即可;
5、 数据会自动存放到对应月份的分区物理数据表中。

分区的调整
如按照上述建表sql建好表,当时间到了2017年1月。所有的数据都会进入pfuture的分区。我们可以通过修改分区来建立新的分区并把数据转移到对应的分区中。
[code type=sql]
ALTER TABLE `book_followed_login_user2` REORGANIZE PARTITION
pfuture
INTO (
PARTITION p201701 VALUES LESS THAN (201702) ENGINE = InnoDB,
PARTITION pfuture VALUES LESS THAN MAXVALUE ENGINE = InnoDB
)
[/code]
修改pfuture,调整为p201701和pfuture两个分区。随着时间的推移,一直增加分区即可。

查看各分区及其中的记录条数
[code type=sql]
SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = ‘book_followed_login_user’
[/code]

删除分区
[code type=sql]
ALTER TABLE tbl DROP PARTITION p20150603;
[/code]

在分区中查询数据
[code type=sql]
SELECT * FROM tbl WHERE `ym` IN (201512, 201511, 201510) AND xxx
[/code]
加上`ym` IN (xxx)的条件。这样只会在三个分区中查询数据,而不会导致扫描所有表。在所有的查询中都应带上`ym`的条件限定分区。

详细的Mysql分区表的使用和一些内容参看另外两篇文章
MySQL的表分区详解
深入了解MySQL分区功能