Spec-Zone.ru › MySQL 9.2

26.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 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)

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

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-9.2-en/partitioning-limitations-partitioning-keys-unique-keys.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API