Spec-Zone .ru
спецификации, руководства, описания, API

17.6.1. Деля Ключи, Первичные ключи, и Уникальные ключи

Этот раздел обсуждает отношение разделения ключей с первичными ключами и уникальными ключами. Правило, управляющее этим отношением, может быть выражено следующим образом: Все столбцы, используемые в выражении разделения для разделенной таблицы, должны быть частью каждого уникального ключа, который может иметь таблица.

Другими словами каждый уникальный ключ на таблице должен использовать каждый столбец в выражении разделения таблицы. (Это также включает первичный ключ таблицы, так как это - по определению уникальный ключ. Этот особый случай обсуждается позже в этом разделе.) Например, каждый из следующих табличных операторов создания недопустим:

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)

Возможно добавить первичный ключ к t_no_pk использование любого из них ALTER TABLE операторы:

#  possible PKmysql> 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 PKmysql> 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 PKmysql> 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 PKmysql> 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 1503mysql> 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)

Следующий ALTER TABLE оператор перестал работать с ошибкой, потому что added столбец не является частью любого уникального ключа в таблице:

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; если Вы хотите разделить эту таблицу, используя какой-либо другой столбец или столбцы в выражении разделения, следует сначала изменить таблицу, или добавляя требуемый столбец или столбцы к первичному ключу, или отбрасывая первичный ключ в целом.