MySQL 5.1 及更高版本支持分区表(partitioned table)。分区在概念上与MERGE存储引擎很相似:他们都可以访问被分别存储在不同地点的多个数据表内容。这两者间的区别是:每个分区数据表都是一个货真价实的数据表,而不是列出各成员数据表的逻辑构造。吃外,分区数据表可以使用MyISAM以外的存储引擎,而MERGE数据表只能用MyISAM数据表来构成。
通过对数据表的存储进行划分,分区数据表具有以下有点:
- 数据表的存储可以分布在多个设备上,这意味着我们可以通过建立某种I/O并行机制缩短反问时间。
- 优化器可以把检索限定在某个分区或同时搜索多个分区
在创建一个分区数据表的时候,先像往常一样在CREATE TABLE 语句里给出数据列和索引的清单,然后用一条PARTITION BY 子句定义一个用来把数据行分配到各个分区的分区函数,再写出其他必须的分区选项即可。分区函数的作用类似于我们在创建MERGE数据表时使用的 INSERT_METHOD选项,只是它更通用:它可以把新数据行分布到所有分区,而INSERT_METHOD选项只能把所有的新数据插入到同一个数据表。
分区函数把新数据分配到不同分区的依据可以是取值范围、值得列表、散列值,如:
- 根据取值范围。数据行所包括的值可以划分为一系列互不冲突的区间,比如日期、收入水平、重量等。
- 根据列表进行划分。每个分区分别对应一个明确的值的列表,比如邮政编码、电话区号等
- 更具散列值进行分区,更具数据行的键值计算出一个散列值,再根据这个散列值把数据分配到各个分区去。你可以自行提供一个散列函数,也可以列出一组数据列让MySQL使用一个内建的散列函数去计算那些数据列的散列值。
分区函数必须具备这样一种确定性:同样的输入永远会把数据分配到同一个分区。按照这一要求,注入RAND()和NOW()之类的函数显然不适合用做分区函数。
一个简单的例子,将2004-2008年期间每一年的日志记录划分到相应的分区表。因为日志记录项中肯定会有一个日期值,所以更具日期划分分区就顺理成章:
CREATE TABLE log_partition
(
dt DATETIME NOT NULL,
info VARCHAR(100) NOT NULL,
INDEX(dt)
)
PARTITION BY RANGE(YEAR(dt))
(
PARTITION p0 VALUES LESS THAN (2005),
PARTITION p1 VALUES LESS THAN (2006),
PARTITION p2 VALUES LESS THAN (2007),
PARTITION p3 VALUES LESS THAN (2008),
PARTITION p4 VALUES LESS THAN MAXVALUE
);
2009年时可以对这个系统分区进行更新:
ALTER TABLE log_partition REORGANIZE PARTITION p4
INTO(
PARTITION p4 VALUES LESS THAN(2009),
PARTITION p5 VALUES LESS THAN MAXVALUE
);