Spec-Zone.ru › MySQL 8.4

26.2.2 Разбиение по списку

Разбиение по списку в MySQL во многом похоже на разбиение по диапазонам. Как и при разбиении по RANGE, каждый раздел должен быть явно определен. Основное различие между этими двумя типами разбиения состоит в том, что при разбиении по списку каждый раздел определяется и выбирается на основе принадлежности значения столбца к одному из набора списков значений, а не к одному из набора непрерывных диапазонов значений. Это делается с помощью PARTITION BY LIST(expr), где expr — это значение столбца или выражение, основанное на значении столбца, возвращающее целое число, а затем каждый раздел определяется с помощью VALUES IN (value_list), где value_list — это список целых чисел, разделенных запятыми.

Примечание

В MySQL 8.4 возможно сопоставление только со списком целых чисел (и, возможно, NULL — см. Раздел 26.2.7, «Как MySQL обрабатывает NULL при разбиении»), при разбиении по LIST.

Однако при использовании разбиения по списку могут использоваться другие типы столбцов в списках значений, что описано далее в этом разделе.

В отличие от разделов, определенных диапазоном, разделы по списку не обязательно должны быть объявлены в определенном порядке. Более подробную синтаксическую информацию см. в Разделе 15.1.20, «Оператор CREATE TABLE».

В следующих примерах предполагается, что основное определение разделяемой таблицы предоставляется оператором CREATE TABLE, показанным здесь:

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT,
    store_id INT
);

(Эта таблица используется в качестве основы для примеров в Разделе 26.2.1, «Разбиение по диапазонам». Как и в других примерах разбиения, предполагается, что default_storage_engine равно InnoDB.)

Предположим, что 20 видеомагазинов распределены по 4 франчайзинговым сетям, как показано в следующей таблице.

Регион Идентификаторы магазинов
Север 3, 5, 6, 9, 17
Восток 1, 2, 10, 11, 19, 20
Запад 4, 12, 13, 14, 18
Центр 7, 8, 15, 16

Для разбиения этой таблицы таким образом, чтобы строки магазинов, относящихся к одному региону, хранились в одном разделе, можно использовать оператор CREATE TABLE, показанный здесь:

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT,
    store_id INT
)
PARTITION BY LIST(store_id) (
    PARTITION pNorth VALUES IN (3,5,6,9,17),
    PARTITION pEast VALUES IN (1,2,10,11,19,20),
    PARTITION pWest VALUES IN (4,12,13,14,18),
    PARTITION pCentral VALUES IN (7,8,15,16)
);

Это упрощает добавление или удаление записей сотрудников, относящихся к конкретным регионам, в таблицу. Например, предположим, что все магазины в регионе Запад проданы другой компании. В MySQL 8.4 все строки, относящиеся к сотрудникам, работающим в магазинах этого региона, могут быть удалены с помощью запроса ALTER TABLE employees TRUNCATE PARTITION pWest, который может выполняться гораздо эффективнее, чем эквивалентный оператор DELETE оператор DELETE FROM employees WHERE store_id IN (4,12,13,14,18);. (Использование ALTER TABLE employees DROP PARTITION pWest также удалит все эти строки, но также удалит раздел pWest из определения таблицы; для восстановления первоначальной схемы разбиения таблицы потребуется использовать оператор ALTER TABLE ... ADD PARTITION.)

Как и при разбиении по RANGE, можно объединить разбиение по LIST с разбиением по хэшу или ключу для создания составного разбиения (подразбиения). См. Раздел 26.2.6, «Подразбиение».

В отличие от разбиения по RANGE, нет “ловушки”, такой как MAXVALUE; все ожидаемые значения для выражения разбиения должны быть покрыты в клаузах PARTITION ... VALUES IN (...). Оператор INSERT, содержащий несоответствующее значение столбца разбиения, завершается ошибкой, как показано в этом примере:

mysql> CREATE TABLE h2 (
    ->   c1 INT,
    ->   c2 INT
    -> )
    -> PARTITION BY LIST(c1) (
    ->   PARTITION p0 VALUES IN (1, 4, 7),
    ->   PARTITION p1 VALUES IN (2, 5, 8)
    -> );
Query OK, 0 rows affected (0.11 sec)

mysql> INSERT INTO h2 VALUES (3, 5);
ERROR 1525 (HY000): Table has no partition for value 3

При вставке нескольких строк с помощью одного оператора INSERT в одну таблицу InnoDB, InnoDB рассматривает оператор как единую транзакцию, поэтому наличие любых несоответствующих значений приводит к полному отказу оператора и вставке строк не происходит.

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

mysql> TRUNCATE h2;
Query OK, 1 row affected (0.00 sec)

mysql> TABLE h2;
Empty set (0.00 sec)

mysql> INSERT IGNORE INTO h2 VALUES (2, 5), (6, 10), (7, 5), (3, 1), (1, 9);
Query OK, 3 rows affected, 2 warnings (0.01 sec)
Records: 5  Duplicates: 2  Warnings: 2

mysql> SHOW WARNINGS;
+---------+------+------------------------------------+
| Level   | Code | Message                            |
+---------+------+------------------------------------+
| Warning | 1526 | Table has no partition for value 6 |
| Warning | 1526 | Table has no partition for value 3 |
+---------+------+------------------------------------+
2 rows in set (0.00 sec)

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

mysql> TABLE h2;
+------+------+
| c1   | c2   |
+------+------+
|    7 |    5 |
|    1 |    9 |
|    2 |    5 |
+------+------+
3 rows in set (0.00 sec)

MySQL также поддерживает разбиение по LIST COLUMNS, разновидность разбиения по LIST, позволяющую использовать столбцы типов, отличных от целого числа, в качестве столбцов разбиения и использовать несколько столбцов в качестве ключей разбиения. Дополнительную информацию см. в Разделе 26.2.3.2, «Разбиение по столбцам списка».

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/partitioning-list.html

Spec-Zone.ru

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