子分区(也称为
复合分区)是分区表中每个分区的进一步划分。考虑以下
CREATE TABLE
语句:
CREATE TABLE ts (id INT, purchased DATE)
PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) )
SUBPARTITIONS 2 (
PARTITION p0 VALUES LESS THAN (1990),
PARTITION p1 VALUES LESS THAN (2000),
PARTITION p2 VALUES LESS THAN MAXVALUE
);
表ts
有 3 个RANGE
分区。这些分区p0
中的每一个—— p1
、 和—— 都p2
进一步分为 2 个子分区。实际上,整个表被划分为多个
3 * 2 = 6
分区。但是,由于PARTITION BY RANGE
子句的作用,前 2 个只存储列中值小于 1990 的那些记录purchased
。
在 MySQL 5.6 中,可以对按RANGE
或
分区的表进行子分区LIST
。子分区可以使用
HASH
或KEY
分区。这也称为复合分区。
SUBPARTITION BY HASH
和
通常分别遵循与和
SUBPARTITION BY KEY
相同的语法规则。一个例外是(与 不同)当前不支持默认列,因此必须指定用于此目的的列,即使该表具有显式主键。这是一个我们正在努力解决的已知问题;有关更多信息和示例,
请参阅
子分区问题。PARTITION BY HASH
PARTITION BY KEY
SUBPARTITION BY
KEY
PARTITION BY KEY
也可以使用
SUBPARTITION
子句显式定义子分区以指定各个子分区的选项。例如,创建与ts
前面示例中所示相同的表的更详细的方式是:
CREATE TABLE ts (id INT, purchased DATE)
PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) (
SUBPARTITION s0,
SUBPARTITION s1
),
PARTITION p1 VALUES LESS THAN (2000) (
SUBPARTITION s2,
SUBPARTITION s3
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s4,
SUBPARTITION s5
)
);
此处列出了一些需要注意的句法项目:
每个分区必须具有相同数量的子分区。
如果您
SUBPARTITION
在分区表的任何分区上显式定义任何子分区,则必须全部定义它们。换句话说,以下语句失败:CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) SUBPARTITION BY HASH( TO_DAYS(purchased) ) ( PARTITION p0 VALUES LESS THAN (1990) ( SUBPARTITION s0, SUBPARTITION s1 ), PARTITION p1 VALUES LESS THAN (2000), PARTITION p2 VALUES LESS THAN MAXVALUE ( SUBPARTITION s2, SUBPARTITION s3 ) );
即使它包含一个
SUBPARTITIONS 2
子句,该语句仍然会失败。每个
SUBPARTITION
子句必须(至少)包含子分区的名称。否则,您可以为子分区设置任何所需的选项或允许它采用该选项的默认设置。子分区名称在整个表中必须是唯一的。例如,以下
CREATE TABLE
语句在 MySQL 5.6 中有效:CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) SUBPARTITION BY HASH( TO_DAYS(purchased) ) ( PARTITION p0 VALUES LESS THAN (1990) ( SUBPARTITION s0, SUBPARTITION s1 ), PARTITION p1 VALUES LESS THAN (2000) ( SUBPARTITION s2, SUBPARTITION s3 ), PARTITION p2 VALUES LESS THAN MAXVALUE ( SUBPARTITION s4, SUBPARTITION s5 ) );
子分区可以与特别大
MyISAM
的表一起使用,以跨多个磁盘分布数据和索引。假设您有 6 个磁盘安装为/disk0
、
/disk1
、/disk2
等。现在考虑以下示例:
CREATE TABLE ts (id INT, purchased DATE)
ENGINE = MYISAM
PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) (
SUBPARTITION s0
DATA DIRECTORY = '/disk0/data'
INDEX DIRECTORY = '/disk0/idx',
SUBPARTITION s1
DATA DIRECTORY = '/disk1/data'
INDEX DIRECTORY = '/disk1/idx'
),
PARTITION p1 VALUES LESS THAN (2000) (
SUBPARTITION s2
DATA DIRECTORY = '/disk2/data'
INDEX DIRECTORY = '/disk2/idx',
SUBPARTITION s3
DATA DIRECTORY = '/disk3/data'
INDEX DIRECTORY = '/disk3/idx'
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s4
DATA DIRECTORY = '/disk4/data'
INDEX DIRECTORY = '/disk4/idx',
SUBPARTITION s5
DATA DIRECTORY = '/disk5/data'
INDEX DIRECTORY = '/disk5/idx'
)
);
在这种情况下,单独的磁盘用于数据和每个RANGE
. 许多其他变化是可能的;另一个例子可能是:
CREATE TABLE ts (id INT, purchased DATE)
ENGINE = MYISAM
PARTITION BY RANGE(YEAR(purchased))
SUBPARTITION BY HASH( TO_DAYS(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) (
SUBPARTITION s0a
DATA DIRECTORY = '/disk0'
INDEX DIRECTORY = '/disk1',
SUBPARTITION s0b
DATA DIRECTORY = '/disk2'
INDEX DIRECTORY = '/disk3'
),
PARTITION p1 VALUES LESS THAN (2000) (
SUBPARTITION s1a
DATA DIRECTORY = '/disk4/data'
INDEX DIRECTORY = '/disk4/idx',
SUBPARTITION s1b
DATA DIRECTORY = '/disk5/data'
INDEX DIRECTORY = '/disk5/idx'
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s2a,
SUBPARTITION s2b
)
);
这里,存储如下:
日期在 1990 年之前的行
purchased
占用大量空间,因此分为 4 种方式,一个单独的磁盘专用于数据和两个子分区(s0a
和s0b
)中的每一个的索引 partitionp0
。换句话说:子分区的数据
s0a
存储在/disk0
.子分区的索引
s0a
存储在/disk1
.子分区的数据
s0b
存储在/disk2
.子分区的索引
s0b
存储在/disk3
.
包含从 1990 年到 1999 年(分区
p1
)的日期的行不需要像 1990 年之前的行那么多的空间。这些被分成 2 个磁盘(/disk4
和/disk5
)而不是 4 个磁盘,就像存储在 中的遗留记录一样p0
:属于
p1
第一个子分区 (s1a
) 的数据和索引存储在/disk4
— 中的数据/disk4/data
和 中的索引/disk4/idx
。属于
p1
第二个子分区 (s1b
) 的数据和索引存储在/disk5
— 中的数据/disk5/data
和 中的索引/disk5/idx
。
反映从 2000 年到现在的日期的行(分区
p2
)占用的空间没有前两个范围中的任何一个所需的空间多。目前,将所有这些存储在默认位置就足够了。将来,当从 2000 年开始的十年的购买数量增长到默认位置不再提供足够空间时,可以使用
ALTER TABLE ... REORGANIZE PARTITION
语句移动相应的行。有关如何完成此操作的说明, 请参见 第 19.3 节,“分区管理” 。
当服务器 SQL 模式生效时,分区定义中不允许
使用DATA DIRECTORY
和选项。在 MySQL 5.6 中,定义子分区时也不允许使用这些选项(错误 #42954)。
INDEX
DIRECTORY
NO_DIR_IN_CREATE