Spec-Zone.ru › MySQL 9.2

26.2.3.1 Разбиение по диапазонам столбцов

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

RANGE COLUMNS разбиение существенно отличается от RANGE разбиения следующим образом:

  • RANGE COLUMNS не принимает выражения, только имена столбцов.

  • RANGE COLUMNS принимает список одного или нескольких столбцов.

    Разбиение по RANGE COLUMNS основано на сравнении кортежей (списков значений столбцов), а не на сравнении скалярных значений. Размещение строк в разделах RANGE COLUMNS также основано на сравнении кортежей; это обсуждается далее в этом разделе.

  • В столбцах разбиения RANGE COLUMNS нет ограничений на целочисленные столбцы; в качестве столбцов разбиения также можно использовать строковые, DATE и DATETIME столбцы. (Подробности см. в разделе 26.2.3, «Разбиение по столбцам»).

Основный синтаксис для создания таблицы, разбитой по RANGE COLUMNS, показан здесь:

CREATE TABLE table_name
PARTITION BY RANGE COLUMNS(column_list) (
    PARTITION partition_name VALUES LESS THAN (value_list)[,
    PARTITION partition_name VALUES LESS THAN (value_list)][,
    ...]
)

column_list:
    column_name[, column_name][, ...]

value_list:
    value[, value][, ...]
Примечание

Здесь показаны не все опции CREATE TABLE, которые можно использовать при создании разбитых таблиц. Полную информацию см. в разделе 15.1.21, «Оператор CREATE TABLE».

В приведенном выше синтаксисе column_list — это список одного или нескольких столбцов (иногда называемый списком столбцов разбиения), а value_list — это список значений (то есть список значений определения разбиения). Для каждого определения разбиения должен быть указан value_list, и каждый value_list должен иметь такое же количество значений, как и column_list столбцов. Как правило, если вы используете N столбцы в ключе COLUMNS, то каждый ключ VALUES LESS THAN также должен быть снабжен списком N значений.

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

mysql> CREATE TABLE rcx (
    ->     a INT,
    ->     b INT,
    ->     c CHAR(3),
    ->     d INT
    -> )
    -> PARTITION BY RANGE COLUMNS(a,d,c) (
    ->     PARTITION p0 VALUES LESS THAN (5,10,'ggg'),
    ->     PARTITION p1 VALUES LESS THAN (10,20,'mmm'),
    ->     PARTITION p2 VALUES LESS THAN (15,30,'sss'),
    ->     PARTITION p3 VALUES LESS THAN (MAXVALUE,MAXVALUE,MAXVALUE)
    -> );
Query OK, 0 rows affected (0.15 sec)

Таблица rcx содержит столбцы a, b, c, d. Список столбцов разбиения, предоставленный в ключе COLUMNS, использует 3 из этих столбцов в порядке a, d, c. Каждый список значений, используемый для определения раздела, содержит 3 значения в том же порядке; то есть каждый кортеж списка значений имеет вид (INT, INT, CHAR(3)), что соответствует типам данных, используемым столбцами a, d и c (в таком порядке).

Размещение строк в разделах определяется путем сравнения кортежа из строки, подлежащей вставке, который соответствует списку столбцов в ключе COLUMNS, с кортежами, используемыми в ключах VALUES LESS THAN для определения разделов таблицы. Поскольку мы сравниваем кортежи (то есть списки или множества значений), а не скалярные значения, семантика VALUES LESS THAN, используемая с RANGE COLUMNS разбиениями, несколько отличается от случая с простыми RANGE разбиениями. При RANGE разбиении строка, генерирующая значение выражения, равное предельному значению в VALUES LESS THAN, никогда не помещается в соответствующий раздел; однако при использовании RANGE COLUMNS разбиения иногда возможно, что строка, чей список столбцов разбиения первый элемент которого равен по значению первому элементу VALUES LESS THAN списка значений, помещается в соответствующий раздел.

Рассмотрим таблицу с RANGE разбиением, созданную этим оператором:

CREATE TABLE r1 (
    a INT,
    b INT
)
PARTITION BY RANGE (a)  (
    PARTITION p0 VALUES LESS THAN (5),
    PARTITION p1 VALUES LESS THAN (MAXVALUE)
);

Если мы вставим 3 строки в эту таблицу таким образом, что значение столбца a равно 5 для каждой строки, все 3 строки хранятся в разделе p1, потому что значение столбца a в каждом случае не меньше 5, как мы можем видеть, выполнив соответствующий запрос к таблице схемы информации PARTITIONS:

mysql> INSERT INTO r1 VALUES (5,10), (5,11), (5,12);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT PARTITION_NAME, TABLE_ROWS
    ->     FROM INFORMATION_SCHEMA.PARTITIONS
    ->     WHERE TABLE_NAME = 'r1';
+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p0             |          0 |
| p1             |          3 |
+----------------+------------+
2 rows in set (0.00 sec)

Теперь рассмотрим аналогичную таблицу rc1, использующую RANGE COLUMNS разбиение с обоими столбцами a и b, указанными в ключе COLUMNS, созданную, как показано здесь:

CREATE TABLE rc1 (
    a INT,
    b INT
)
PARTITION BY RANGE COLUMNS(a, b) (
    PARTITION p0 VALUES LESS THAN (5, 12),
    PARTITION p3 VALUES LESS THAN (MAXVALUE, MAXVALUE)
);

Если мы вставим в rc1 точно такие же строки, как мы только что вставили в r1, распределение строк будет совершенно другим:

mysql> INSERT INTO rc1 VALUES (5,10), (5,11), (5,12);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT PARTITION_NAME, TABLE_ROWS
    ->     FROM INFORMATION_SCHEMA.PARTITIONS
    ->     WHERE TABLE_NAME = 'rc1';
+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p0             |          2 |
| p3             |          1 |
+----------------+------------+
2 rows in set (0.00 sec)

Это потому, что мы сравниваем строки, а не скалярные значения. Мы можем сравнить вставленные значения строк с предельным значением строки из ключа VALUES THAN LESS THAN, используемого для определения раздела p0 в таблице rc1, так:

mysql> SELECT (5,10) < (5,12), (5,11) < (5,12), (5,12) < (5,12);
+-----------------+-----------------+-----------------+
| (5,10) < (5,12) | (5,11) < (5,12) | (5,12) < (5,12) |
+-----------------+-----------------+-----------------+
|               1 |               1 |               0 |
+-----------------+-----------------+-----------------+
1 row in set (0.00 sec)

Два кортежа (5,10) и (5,11) оцениваются как меньше (5,12), поэтому они хранятся в разделе p0. Поскольку 5 не меньше 5 и 12 не меньше 12, (5,12) считается не меньше (5,12) и хранится в разделе p1.

Оператор SELECT в приведенном выше примере также можно было написать с использованием явных конструкторов строк, например, так:

SELECT ROW(5,10) < ROW(5,12), ROW(5,11) < ROW(5,12), ROW(5,12) < ROW(5,12);

Дополнительную информацию об использовании конструкторов строк в MySQL см. в разделе 15.2.15.5, «Подзапросы с строками».

Для таблицы, разбитой по RANGE COLUMNS, использующей только один столбец разбиения, хранение строк в разделах такое же, как и для эквивалентной таблицы, разбитой по RANGE. Следующий оператор CREATE TABLE создает таблицу, разбитую по RANGE COLUMNS, используя 1 столбец разбиения:

CREATE TABLE rx (
    a INT,
    b INT
)
PARTITION BY RANGE COLUMNS (a)  (
    PARTITION p0 VALUES LESS THAN (5),
    PARTITION p1 VALUES LESS THAN (MAXVALUE)
);

Если мы вставим строки (5,10), (5,11) и (5,12) в эту таблицу, мы можем увидеть, что их размещение такое же, как и в таблице r, которую мы создали и заполнили ранее:

mysql> INSERT INTO rx VALUES (5,10), (5,11), (5,12);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT PARTITION_NAME,TABLE_ROWS
    ->     FROM INFORMATION_SCHEMA.PARTITIONS
    ->     WHERE TABLE_NAME = 'rx';
+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p0             |          0 |
| p1             |          3 |
+----------------+------------+
2 rows in set (0.00 sec)

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

CREATE TABLE rc2 (
    a INT,
    b INT
)
PARTITION BY RANGE COLUMNS(a,b) (
    PARTITION p0 VALUES LESS THAN (0,10),
    PARTITION p1 VALUES LESS THAN (10,20),
    PARTITION p2 VALUES LESS THAN (10,30),
    PARTITION p3 VALUES LESS THAN (MAXVALUE,MAXVALUE)
 );

CREATE TABLE rc3 (
    a INT,
    b INT
)
PARTITION BY RANGE COLUMNS(a,b) (
    PARTITION p0 VALUES LESS THAN (0,10),
    PARTITION p1 VALUES LESS THAN (10,20),
    PARTITION p2 VALUES LESS THAN (10,30),
    PARTITION p3 VALUES LESS THAN (10,35),
    PARTITION p4 VALUES LESS THAN (20,40),
    PARTITION p5 VALUES LESS THAN (MAXVALUE,MAXVALUE)
 );

Следующий оператор также успешно выполняется, хотя на первый взгляд может показаться, что это не так, поскольку предельное значение столбца b равно 25 для раздела p0 и 20 для раздела p1, а предельное значение столбца c равно 100 для раздела p1 и 50 для раздела p2:

CREATE TABLE rc4 (
    a INT,
    b INT,
    c INT
)
PARTITION BY RANGE COLUMNS(a,b,c) (
    PARTITION p0 VALUES LESS THAN (0,25,50),
    PARTITION p1 VALUES LESS THAN (10,20,100),
    PARTITION p2 VALUES LESS THAN (10,30,50),
    PARTITION p3 VALUES LESS THAN (MAXVALUE,MAXVALUE,MAXVALUE)
 );

При проектировании таблиц, разбитых по RANGE COLUMNS, вы всегда можете проверить последовательные определения разделов, сравнив желаемые кортежи с помощью клиента mysql, например так:

mysql> SELECT (0,25,50) < (10,20,100), (10,20,100) < (10,30,50);
+-------------------------+--------------------------+
| (0,25,50) < (10,20,100) | (10,20,100) < (10,30,50) |
+-------------------------+--------------------------+
|                       1 |                        1 |
+-------------------------+--------------------------+
1 row in set (0.00 sec)

Если оператор CREATE TABLE содержит определения разделов, которые не упорядочены по строго возрастанию, он завершается ошибкой, как показано в этом примере:

mysql> CREATE TABLE rcf (
    ->     a INT,
    ->     b INT,
    ->     c INT
    -> )
    -> PARTITION BY RANGE COLUMNS(a,b,c) (
    ->     PARTITION p0 VALUES LESS THAN (0,25,50),
    ->     PARTITION p1 VALUES LESS THAN (20,20,100),
    ->     PARTITION p2 VALUES LESS THAN (10,30,50),
    ->     PARTITION p3 VALUES LESS THAN (MAXVALUE,MAXVALUE,MAXVALUE)
    ->  );
ERROR 1493 (HY000): VALUES LESS THAN value must be strictly increasing for each partition

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

mysql> SELECT (0,25,50) < (20,20,100), (20,20,100) < (10,30,50);
+-------------------------+--------------------------+
| (0,25,50) < (20,20,100) | (20,20,100) < (10,30,50) |
+-------------------------+--------------------------+
|                       1 |                        0 |
+-------------------------+--------------------------+
1 row in set (0.00 sec)

Также возможно, что MAXVALUE для одного столбца появится в нескольких VALUES LESS THAN-запросах при использовании RANGE COLUMNS. Однако предельные значения для отдельных столбцов в последовательных определениях разбиения должны быть возрастающими, не должно быть более одного разбиения, где MAXVALUE используется в качестве верхнего предела для всех значений столбцов, и это определение разбиения должно быть последним в списке PARTITION ... VALUES LESS THAN-запросов. Кроме того, вы не можете использовать MAXVALUE в качестве предельного значения для первого столбца в более чем одном определении разбиения.

Как уже отмечалось, при разбиении с помощью RANGE COLUMNS можно использовать столбцы с нецелыми значениями в качестве столбцов разбиения. (См. Раздел 26.2.3, «COLUMNS Partitioning», для полного списка таких столбцов). Рассмотрим таблицу с именем employees (которая не разбита), созданную с помощью следующей команды:

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 NOT NULL,
    store_id INT NOT NULL
);

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

CREATE TABLE employees_by_lname (
    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 NOT NULL,
    store_id INT NOT NULL
)
PARTITION BY RANGE COLUMNS (lname)  (
    PARTITION p0 VALUES LESS THAN ('g'),
    PARTITION p1 VALUES LESS THAN ('m'),
    PARTITION p2 VALUES LESS THAN ('t'),
    PARTITION p3 VALUES LESS THAN (MAXVALUE)
);

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

ALTER TABLE employees PARTITION BY RANGE COLUMNS (lname)  (
    PARTITION p0 VALUES LESS THAN ('g'),
    PARTITION p1 VALUES LESS THAN ('m'),
    PARTITION p2 VALUES LESS THAN ('t'),
    PARTITION p3 VALUES LESS THAN (MAXVALUE)
);
Примечание

Поскольку разные наборы символов и правила сортировки имеют различные порядки сортировки, используемые наборы символов и правила сортировки могут повлиять на то, в какое разбиение таблицы, разбиение по RANGE COLUMNS, будет помещена заданная строка при использовании столбцов со строковыми значениями в качестве столбцов разбиения. Кроме того, изменение набора символов или правила сортировки для базы данных, таблицы или столбца после создания такой таблицы может привести к изменениям в распределении строк. Например, при использовании чувствительного к регистру правила сортировки 'and' сортируется перед 'Andersen', но при использовании правила сортировки, нечувствительного к регистру, наоборот.

Сведения о том, как MySQL обрабатывает наборы символов и правила сортировки, см. в Главе 12, Наборы символов, правила сортировки, Unicode.

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

ALTER TABLE employees PARTITION BY RANGE COLUMNS (hired)  (
    PARTITION p0 VALUES LESS THAN ('1970-01-01'),
    PARTITION p1 VALUES LESS THAN ('1980-01-01'),
    PARTITION p2 VALUES LESS THAN ('1990-01-01'),
    PARTITION p3 VALUES LESS THAN ('2000-01-01'),
    PARTITION p4 VALUES LESS THAN ('2010-01-01'),
    PARTITION p5 VALUES LESS THAN (MAXVALUE)
);

Дополнительные сведения о синтаксисе PARTITION BY RANGE COLUMNS см. в Разделе 15.1.21, «CREATE TABLE Statement».

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

Spec-Zone.ru

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