本節討論分割鍵與主鍵和唯一鍵之間的關係。控制此關係的規則可以表示如下:分割資料表的分割運算式中使用的所有欄位都必須是資料表可能擁有的每個唯一鍵的一部分。
換句話說,資料表上的每個唯一鍵都必須使用資料表分割運算式中的每個欄位。(這也包括資料表的主鍵,因為根據定義它是唯一鍵。本節稍後將討論這種特殊情況。)例如,以下每個資料表建立陳述式都無效
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;
在每種情況下,建議的資料表都將至少有一個不包含分割運算式中使用的所有欄位的唯一鍵。
以下每個陳述式都有效,並且表示可以使相應的無效資料表建立陳述式運作的一種方式
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;
此範例顯示在這種情況下產生的錯誤
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
都包含在建議的分割鍵中,但這兩個欄位都不是資料表上兩個唯一鍵的一部分。這顯示了修正無效資料表定義的一種可能方法
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
是兩個唯一鍵的一部分,並且資料表建立陳述式成功。
以下資料表完全無法分割區,因為無法將任何屬於兩個唯一鍵的欄位包含在分割鍵中
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)
);
由於每個主鍵根據定義都是唯一鍵,因此此限制也包括資料表的主鍵(如果有的話)。例如,接下來的兩個陳述式無效
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;
在這兩種情況下,主鍵都不包括分割運算式中引用的所有欄位。但是,接下來的兩個陳述式都有效
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;
如果資料表沒有唯一鍵(包括沒有主鍵),則此限制不適用,並且您可以在分割運算式中使用任何欄位或多個欄位,只要欄位類型與分割類型相容即可。
出於同樣的原因,除非索引鍵包含資料表分割運算式使用的所有欄位,否則您稍後無法將唯一鍵新增至分割資料表。請考慮按此處所示建立的分割資料表
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)
可以使用以下任一 ALTER TABLE
陳述式將主鍵新增至 t_no_pk
# 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
是分割鍵的一部分,但不是建議的主鍵的一部分
# 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
的唯一鍵。
這些規則也適用於您希望使用 ALTER TABLE ... PARTITION BY
分割的現有非分割資料表。請考慮按此處所示建立的資料表 np_pk
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)
由於 added
欄位不是資料表中任何唯一鍵的一部分,因此以下 ALTER 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
欄位作為分割欄位的陳述式有效
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
;如果您希望使用分割運算式中的任何其他欄位或多個欄位分割此資料表,您必須先修改資料表,方法是將所需的欄位或多個欄位新增至主鍵,或是完全捨棄主鍵。