MySQL 分区表

水平分区

  在 MySQL 中,如果一张表的数据量太大(例如包含百万行数据),为了让表变得方便管理,可以将表拆分成多个分区。MySQL 只支持水平分区,不支持垂直分区。如果使用水平分区,那么 MySQL 会根据用户定义的规则,将表中不同的行拆分到不同的分区。

分区的好处

  通常来说,如果打算让一张表存储大量的数据,那么才值得对它进行分区,分区会带来一些好处:

  • 分区表的数据可以分布在文件系统的不同位置,甚至是多个磁盘,这使得分区表可以容纳更多数据。
  • 可以通过删除没有用的分区来删除数据,这种情况下可以很快地删除数据。
  • 可以加快查询的执行速度,因为对于某些查询来说,只需要查询某个分区即可。

分区的限制

  在 MySQL 中,创建分区表时候有一个限制条件:分区表中的每个唯一索引(包括主键),都必须包含分区表达式中的所有列。让我们举个例子:

1
2
3
4
5
6
7
8
9
10
CREATE TABLE userslogs (
id INT NOT NULL AUTO_INCREMENT,
username VARCHAR(20) NOT NULL,
logdata BLOB NOT NULL,
created DATETIME NOT NULL,
PRIMARY KEY(id),
UNIQUE KEY (username, created)
)
PARTITION BY HASH(TO_DAYS(created))
PARTITIONS 10;

  执行这个 SQL 语句将会报错:

1
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

  这个错误说的是,主键id并没有包含分区列created,所以导致建表失败。下面的建表语句则可以执行成功:

1
2
3
4
5
6
7
8
CREATE TABLE userslogs (
username VARCHAR(20) NOT NULL,
logdata BLOB NOT NULL,
created DATETIME NOT NULL,
PRIMARY KEY(username, created)
)
PARTITION BY HASH( TO_DAYS(created) )
PARTITIONS 10;

  这个表的主键(username, created)包含了分区列created,所以建表可以成功。

分区的类型

  最常见的分区类型大概就是RANGE类型了,RANGE分区的规则很简单:

  • 为每个分区都指定一个分区范围。
  • 这些范围必须保证是连续的,并且不能发生重叠。
  • 分区表达式必须返回整数或者 NULL 类型。

  下面我们创建一个RANGE分区:

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE userslogs_range (
username VARCHAR(20) NOT NULL,
logdata BLOB NOT NULL,
created DATETIME NOT NULL,
PRIMARY KEY(username, created)
)
PARTITION BY RANGE( YEAR(created) )(
PARTITION from_2013_or_less VALUES LESS THAN (2014),
PARTITION from_2014 VALUES LESS THAN (2015),
PARTITION from_2015 VALUES LESS THAN (2016),
PARTITION from_2016_and_up VALUES LESS THAN MAXVALUE);

参考资料