Spec-Zone.ru › MySQL 5.7

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

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

Примечание

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

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

В отличие от разделов, определённых диапазоном, разделы по списку не обязательно должны быть объявлены в определённом порядке. Более подробную информацию о синтаксисе см. в Разделе 13.1.18, «Оператор 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
);

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

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

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

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

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

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

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

Spec-Zone.ru

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