在MySQL 中,支持对表创建分区,主要的分区类型有Range 分区、List 分区、Hash 分区、Key 分区和子分区。
最近在项目中使用到Range 分区,将数据表进行了分区;Range 分区基于属于一个给定连续区间的列值,把多行分配给分区。每个分区包含那些分区表达式的值位于一个给定的连续区间内的行。这些区间要连续且不能相互重叠,使用VALUES LESS THAN 操作符来进行定义。在下面的几个例子中,假定你创建了一个如下的一个表,该表保存有20 家音像店的职员记录,这20 家音像店的编号从1 到20 :
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
);
根据你的需要,这个表可以有多种方式来按照区间进行分区。一种方式是使用store_id 列。例如,你可能决定通过添加一个PARTITION BY RANGE 子句把这个表分割成4 个区间,如下所示:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN (21)
);
按照这种分区方案,在商店1 到5 工作的雇员相对应的所有行被保存在分区P0 中,商店6 到10 的雇员保存在P1 中,依次类推。注意,每个分区都是按顺序进行定义,从最低到最高。这是PARTITION BY RANGE 语法的要求;在这点上,它类似于C 或Java 中的“switch ... case ”语句。
对于包含数据(72, 'Michael', 'Widenius', '1998-06-25', NULL, 13) 的一个新行,可以很容易地确定它将插入到p2 分区中,但是如果增加了一个编号为第21 的商店,将会发生什么呢?在这种方案下,由于没有规则把store_id 大于20 的商店包含在内,服务器将不知道把该行保存在何处,将会导致错误。 要避免这种错误,可以通过在CREATE TABLE 语句中使用一个“catchall ” VALUES LESS THAN 子句,该子句提供给所有大于明确指定的最高值的值:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN MAXVALUE
);
MAXVALUE 表示最大的可能的整数值。现在,store_id 列值大于或等于16 (定义了的最高值)的所有行都将保存在分区p3 中。在将来的某个时候,当商店数已经增长到25, 30, 或更多 ,可以使用ALTER TABLE 语句为商店21-25, 26-30, 等等增加新的分区 。
在几乎一样的结构中,你还可以基于雇员的工作代码来分割表,也就是说,基于job_code 列值的连续区间。例如——假定2 位数字的工作代码用来表示普通(店内的)工人,三个数字代码表示办公室和支持人员,四个数字代码表示管理层,你可以使用下面的语句创建该分区表:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (job_code) (
PARTITION p0 VALUES LESS THAN (100),
PARTITION p1 VALUES LESS THAN (1000),
PARTITION p2 VALUES LESS THAN (10000)
);
在这个例子中, 店内工人相关的所有行将保存在分区p0 中,办公室和支持人员相关的所有行保存在分区p1 中,管理层相关的所有行保存在分区p2 中。
在VALUES LESS THAN 子句中使用一个表达式也是可能的。这里最值得注意的限制是MySQL 必须能够计算表达式的返回值作为LESS THAN (<) 比较的一部分;因此,表达式的值不能为NULL 。由于这个原因,雇员表的hired, separated, job_code, 和store_id 列已经被定义为非空(NOT NULL )。