本节讨论分区键与主键和唯一键的关系。该关系的规则可表述如下:用于分区表的分区表达式中的所有列必须是该表可能具有的每个唯一键的一部分。This section discusses the relationship of partitioning keys with primary keys and unique keys. The rule governing this relationship can be expressed as follows: All columns used in the partitioning expression for a partitioned table must be part of every unique key that the table may have.
换句话说,表中的每一个唯一键都必须使用表分区表达式中的每一列。 (这也包括表的主键,因为它本质上就是唯一键。这种特殊情况将在本节后面讨论。) 例如,下面的每个建表语句都是无效的:In other words, every unique key on the table must use every column in the table's partitioning expression. (This also includes the table's primary key, since it is by definition a unique key. This particular case is discussed later in this section.) For example, each of the following table creation statements is invalid:
CREATE TABLE t1 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
UNIQUE KEY (col1, col2)
)
PARTITION BY HASH(col3)
PARTITIONS 4;
CREATE TABLE t2 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
UNIQUE KEY (col1),
UNIQUE KEY (col3)
)
PARTITION BY HASH(col1 + col3)
PARTITIONS 4;
在每种情况下,所提议的表至少有一个唯一键未包含分区表达式中使用的所有列。In each case, the proposed table would have at least one unique key that does not include all columns used in the partitioning expression.
下面的每个语句都是有效的,并表示使对应的无效建表语句生效的一种方式:Each of the following statements is valid, and represents one way in which the corresponding invalid table creation statement could be made to work:
CREATE TABLE t1 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
UNIQUE KEY (col1, col2, col3)
)
PARTITION BY HASH(col3)
PARTITIONS 4;
CREATE TABLE t2 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
UNIQUE KEY (col1, col3)
)
PARTITION BY HASH(col1 + col3)
PARTITIONS 4;
此示例显示了在这种情况下产生的错误:This example shows the error produced in such cases:
mysql>CREATE TABLE t3 (->col1 INT NOT NULL,->col2 DATE NOT NULL,->col3 INT NOT NULL,->col4 INT NOT NULL,->UNIQUE KEY (col1, col2),->UNIQUE KEY (col3)->)->PARTITION BY HASH(col1 + col3)->PARTITIONS 4;ERROR 1491 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function
CREATE TABLE 语句失败,因为提议的分区键中同时包含了 col1 和 col3,但这两列都不属于表上所有唯一键的组成部分。这显示了一个修复无效表定义的可能方法:The CREATE TABLE statement fails
because both col1 and col3
are included in the proposed partitioning key, but neither of
these columns is part of both of unique keys on the table. This
shows one possible fix for the invalid table definition:
mysql>CREATE TABLE t3 (->col1 INT NOT NULL,->col2 DATE NOT NULL,->col3 INT NOT NULL,->col4 INT NOT NULL,->UNIQUE KEY (col1, col2, col3),->UNIQUE KEY (col3)->)->PARTITION BY HASH(col3)->PARTITIONS 4;Query OK, 0 rows affected (0.05 sec)
在这种情况下,提议的分区键 col3 属于两个唯一键,因此表创建语句成功。In this case, the proposed partitioning key
col3 is part of both unique keys, and the
table creation statement succeeds.
下面的表完全无法分区,因为没有办法在分区键中包含属于两个唯一键的任何列:The following table cannot be partitioned at all, because there is no way to include in a partitioning key any columns that belong to both unique keys:
CREATE TABLE t4 (
col1 INT NOT NULL,
col2 INT NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
UNIQUE KEY (col1, col3),
UNIQUE KEY (col2, col4)
);
由于每个主键按定义都是唯一键,因此如果表有主键,这一限制也包括表的主键。例如,下面的两条语句是无效的:Since every primary key is by definition a unique key, this restriction also includes the table's primary key, if it has one. For example, the next two statements are invalid:
CREATE TABLE t5 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
PRIMARY KEY(col1, col2)
)
PARTITION BY HASH(col3)
PARTITIONS 4;
CREATE TABLE t6 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
PRIMARY KEY(col1, col3),
UNIQUE KEY(col2)
)
PARTITION BY HASH( YEAR(col2) )
PARTITIONS 4;
在这两种情况下,主键都未包含分区表达式中引用的所有列。不过,接下来的两个语句都是有效的:In both cases, the primary key does not include all columns referenced in the partitioning expression. However, both of the next two statements are valid:
CREATE TABLE t7 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
PRIMARY KEY(col1, col2)
)
PARTITION BY HASH(col1 + YEAR(col2))
PARTITIONS 4;
CREATE TABLE t8 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
PRIMARY KEY(col1, col2, col4),
UNIQUE KEY(col2, col1)
)
PARTITION BY HASH(col1 + YEAR(col2))
PARTITIONS 4;
如果表没有唯一键——这包括没有主键——那么这个限制不适用,并且你可以在分区表达式中使用任何列,只要列类型与分区类型兼容。If a table has no unique keys—this includes having no primary key—then this restriction does not apply, and you may use any column or columns in the partitioning expression as long as the column type is compatible with the partitioning type.
出于同样的原因,你不能随后向分区表添加唯一键,除非该键包含表的分区表达式中使用的所有列。考虑如下所示创建的分区表:For the same reason, you cannot later add a unique key to a partitioned table unless the key includes all columns used by the table's partitioning expression. Consider the partitioned table created as shown here:
mysql>CREATE TABLE t_no_pk (c1 INT, c2 INT)->PARTITION BY RANGE(c1) (->PARTITION p0 VALUES LESS THAN (10),->PARTITION p1 VALUES LESS THAN (20),->PARTITION p2 VALUES LESS THAN (30),->PARTITION p3 VALUES LESS THAN (40)->);Query OK, 0 rows affected (0.12 sec)
可以使用以下任一 t_no_pk 语句向 ALTER
TABLE 添加主键:It is possible to add a primary key to
t_no_pk using either of these
ALTER
TABLE statements:
# possible PK mysql>ALTER TABLE t_no_pk ADD PRIMARY KEY(c1);Query OK, 0 rows affected (0.13 sec) Records: 0 Duplicates: 0 Warnings: 0 # drop this PK mysql>ALTER TABLE t_no_pk DROP PRIMARY KEY;Query OK, 0 rows affected (0.10 sec) Records: 0 Duplicates: 0 Warnings: 0 # use another possible PK mysql>ALTER TABLE t_no_pk ADD PRIMARY KEY(c1, c2);Query OK, 0 rows affected (0.12 sec) Records: 0 Duplicates: 0 Warnings: 0 # drop this PK mysql>ALTER TABLE t_no_pk DROP PRIMARY KEY;Query OK, 0 rows affected (0.09 sec) Records: 0 Duplicates: 0 Warnings: 0
然而,下一条语句失败,因为 c1 是分区键的一部分,但不是建议的主键的一部分:However, the next statement fails, because c1
is part of the partitioning key, but is not part of the proposed
primary key:
# fails with error 1503
mysql> ALTER TABLE t_no_pk ADD PRIMARY KEY(c2);
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function
由于 t_no_pk 的分区表达式中只有 c1,尝试仅在 c2 上添加唯一键会失败。然而,您可以添加一个使用 c1 和 c2 的唯一键。Since t_no_pk has only c1
in its partitioning expression, attempting to adding a unique
key on c2 alone fails. However, you can add a
unique key that uses both c1 and
c2.
这些规则同样适用于您希望使用 ALTER
TABLE ... PARTITION BY 进行分区的现有非分区表。考虑如下创建的表 np_pk:These rules also apply to existing nonpartitioned tables that
you wish to partition using
ALTER
TABLE ... PARTITION BY. Consider a table
np_pk created as shown here:
mysql>CREATE TABLE np_pk (->id INT NOT NULL AUTO_INCREMENT,->name VARCHAR(50),->added DATE,->PRIMARY KEY (id)->);Query OK, 0 rows affected (0.08 sec)
以下 ALTER
TABLE 语句会出错,因为 added 列不属于表中的任何唯一键:The following
ALTER
TABLE statement fails with an error, because the
added column is not part of any unique key in
the table:
mysql>ALTER TABLE np_pk->PARTITION BY HASH( TO_DAYS(added) )->PARTITIONS 4;ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function
然而,使用 id 列作为分区列的语句是有效的,如下所示:However, this statement using the id column
for the partitioning column is valid, as shown here:
mysql>ALTER TABLE np_pk->PARTITION BY HASH(id)->PARTITIONS 4;Query OK, 0 rows affected (0.11 sec) Records: 0 Duplicates: 0 Warnings: 0
在 np_pk 的情况下,唯一可以用作分区表达式的一部分的列是 id;如果您希望使用其他列作为分区表达式的一部分对该表进行分区,您必须先修改表,要么将所需的列添加到主键,要么完全删除主键。In the case of np_pk, the only column that
may be used as part of a partitioning expression is
id; if you wish to partition this table using
any other column or columns in the partitioning expression, you
must first modify the table, either by adding the desired column
or columns to the primary key, or by dropping the primary key
altogether.