Spec-Zone.ru › MySQL 8.4

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.20, «Запрос CREATE TABLE».

В только что показанном синтаксисе column_list — это список одного или нескольких столбцов (иногда называемый списком столбцов разбиения), а value_list — это список значений (то есть это список значений определения разбиения). Для каждого определения разбиения необходимо указать value_list, и каждый value_list должен содержать столько значений, сколько столбцов в column_list. Если в вашем запросе COLUMNS используются N столбцы, то каждый 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 разбиение, в котором в предложении COLUMNS указаны столбцы a и b, созданная, как показано здесь:

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, «Разбиение по столбцам» для полного списка таких столбцов.) Рассмотрим таблицу с именем 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.20, «Оператор CREATE TABLE».

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

Spec-Zone.ru

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