Spec-Zone.ru › MySQL 5.7

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

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

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

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

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

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

  • Столбцы разбиения по RANGE COLUMNS не ограничены целочисленными столбцами; также можно использовать строковые, DATE и DATETIME столбцы в качестве столбцов разбиения. (Подробности см. в разделе Раздел 22.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 параметры, которые могут быть использованы при создании разбиений таблиц, показаны здесь. Для получения полной информации см. раздел 13.1.18, «Заявление 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 см. в разделе Раздел 13.2.10.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)
END_OF_DOCUMENT_MARKER

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

Как уже отмечалось, при разбиении с использованием RANGE COLUMNS также можно использовать столбцы с нецелыми значениями в качестве столбцов разбиения. (См. Раздел 22.2.3, «Разбиение по столбцам» для полного списка таких столбцов.) Рассмотрим таблицу с именем 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 обрабатывает наборы символов и правила сортировки, см. в Главе 10, Наборы символов, правила сортировки, 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 см. в Разделе 13.1.18, «Оператор CREATE TABLE».

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

Spec-Zone.ru

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