Spec-Zone .ru
спецификации, руководства, описания, API

17.3.1. Управление RANGE и LISTРазделы

Диапазон и разделы списка очень подобны относительно того, как добавление и отбрасывание разделов обрабатываются. По этой причине мы обсуждаем управление обоими видами разделения в этом разделе. Для получения информации о работе с таблицами, которые делятся хешем или ключом, см. Раздел 17.3.2, "Управление HASH и KEY Разделы" . Отбрасывание a RANGE или LIST раздел является более прямым чем добавление того, таким образом, мы обсуждаем это сначала.

Отбрасывание раздела от таблицы, которая делится также RANGE или LIST может быть выполнен, используя ALTER TABLE оператор с a DROP PARTITION пункт. Вот очень основной пример, который предполагает, что Вы уже составили таблицу, которая делится диапазоном и затем заполняется с 10 записями, используя следующий CREATE TABLE и INSERT операторы:

mysql> CREATE TABLE tr (id INT, name VARCHAR(50),
        purchased DATE)    ->     PARTITION BY RANGE( YEAR(purchased)
        ) (    ->         PARTITION p0 VALUES LESS THAN
        (1990),    ->         PARTITION p1 VALUES LESS THAN
        (1995),    ->         PARTITION p2 VALUES LESS THAN
        (2000),    ->         PARTITION p3 VALUES LESS THAN
        (2005)    ->     );Query OK, 0 rows affected (0.01 sec)mysql> INSERT INTO tr VALUES    ->     (1,
        'desk organiser', '2003-10-15'),    ->     (2, 'CD player',
        '1993-11-05'),    ->     (3, 'TV set', '1996-03-10'),    ->     (4, 'bookcase', '1982-01-10'),    ->     (5, 'exercise bike', '2004-05-09'),    ->     (6, 'sofa', '1987-06-05'),    ->     (7, 'popcorn maker', '2001-11-22'),    ->     (8, 'aquarium', '1992-08-04'),    ->     (9, 'study desk', '1984-09-16'),    ->     (10, 'lava lamp', '1998-12-25');Query OK, 10 rows affected (0.01 sec)

Можно видеть, какие элементы должны были быть вставлены в раздел p2 как показано здесь:

mysql> SELECT * FROM
        tr    -> WHERE purchased BETWEEN '1995-01-01' AND
        '1999-12-31';+------+-----------+------------+| id   | name      | purchased  |+------+-----------+------------+|    3 | TV set    | 1996-03-10 ||   10 | lava lamp | 1998-12-25 |+------+-----------+------------+2 rows in set (0.00 sec)

Отбрасывать названный раздел p2, выполните следующую команду:

mysql> ALTER TABLE tr DROP PARTITION
        p2;Query OK, 0 rows affected (0.03 sec)

Очень важно помнить, что, когда Вы отбрасываете раздел, Вы также удаляете все данные, которые хранились в том разделе. Можно видеть что дело обстоит так, запуская повторно предыдущее SELECT запрос:

mysql> SELECT * FROM tr WHERE
        purchased    -> BETWEEN '1995-01-01' AND '1999-12-31';Empty set (0.00 sec)

Из-за этого Вы должны иметь DROP полномочие для таблицы прежде, чем можно будет выполниться ALTER TABLE ... DROP PARTITION на той таблице.

Если Вы хотите отбросить все данные от всех разделов, сохраняя табличное определение и его схему выделения разделов, используйте TRUNCATE TABLE оператор. (См. Раздел 13.1.27,"TRUNCATE TABLE Синтаксис".)

Если Вы намереваетесь изменить разделение таблицы, не теряя данные, использовать ALTER TABLE ... REORGANIZE PARTITION вместо этого. См. ниже или в Разделе 13.1.6,"ALTER TABLE Синтаксис", для информации о REORGANIZE PARTITION.

Если Вы теперь выполняете a SHOW CREATE TABLE оператор, можно видеть, как состав разделения таблицы был изменен:

mysql> SHOW CREATE TABLE tr\G*************************** 1. row ***************************       Table: trCreate Table: CREATE TABLE `tr` (  `id` int(11) default NULL,  `name` varchar(50) default NULL,  `purchased` date default NULL) ENGINE=MyISAM DEFAULT CHARSET=latin1PARTITION BY RANGE ( YEAR(purchased) ) (  PARTITION p0 VALUES LESS THAN (1990) ENGINE = MyISAM,  PARTITION p1 VALUES LESS THAN (1995) ENGINE = MyISAM,  PARTITION p3 VALUES LESS THAN (2005) ENGINE = MyISAM)1 row in set (0.01 sec)

Когда Вы вставляете новые строки в измененную таблицу с purchased значения столбцов между '1995-01-01' и '2004-12-31' включительно, те строки будут сохранены в разделе p3. Можно проверить это следующим образом:

mysql> INSERT INTO tr VALUES (11, 'pencil holder',
        '1995-07-12');Query OK, 1 row affected (0.00 sec)mysql> SELECT
        * FROM tr WHERE purchased    -> BETWEEN '1995-01-01' AND
        '2004-12-31';+------+----------------+------------+| id   | name           | purchased  |+------+----------------+------------+|   11 | pencil holder  | 1995-07-12 ||    1 | desk organiser | 2003-10-15 ||    5 | exercise bike  | 2004-05-09 ||    7 | popcorn maker  | 2001-11-22 |+------+----------------+------------+4 rows in set (0.00 sec)mysql> ALTER TABLE tr DROP PARTITION p3;Query OK, 0 rows affected (0.03 sec)mysql> SELECT * FROM tr WHERE purchased    -> BETWEEN
        '1995-01-01' AND '2004-12-31';Empty set (0.00 sec)

Отметьте что число строк, отброшенных от таблицы в результате ALTER TABLE ... DROP PARTITION не сообщается сервером, как это было бы эквивалентом DELETE запрос.

Отбрасывание LIST разделы используют точно то же самое ALTER TABLE ... DROP PARTITION синтаксис как использующийся для того, чтобы отбросить RANGE разделы. Однако, есть одно важное различие в эффекте, который это имеет на Ваше использование таблицы позже: больше невозможно вставить в таблицу строки, имеющие любое из значений, которые были включены в список значения, определяющий удаленный раздел. (См. Раздел 17.2.2,"LIST Разделение", для примера.)

Чтобы добавить новый диапазон или раздел списка к ранее разделенной таблице, используйте ALTER TABLE ... ADD PARTITION оператор. Для таблиц, которые делятся RANGE, это может использоваться, чтобы добавить новый диапазон до конца списка существующих разделов. Предположите, что у Вас есть разделенная таблица, содержащая данные членства для Вашей организации, которая определяется следующим образом:

CREATE TABLE members (    id INT,    fname VARCHAR(25),    lname VARCHAR(25),    dob DATE)PARTITION BY RANGE( YEAR(dob) ) (    PARTITION p0 VALUES LESS THAN (1970),    PARTITION p1 VALUES LESS THAN (1980),    PARTITION p2 VALUES LESS THAN (1990));

Предположите далее, что минимальный возраст для элементов 16. Поскольку календарь приближается к концу 2005, Вы понимаете, что будете скоро принимать членов, кто родился в 1990 (и позже в последующие годы). Можно изменить members таблица, чтобы разместить новые элементы, перенесенные в годах 1990 - 1999 как показано здесь:

ALTER TABLE members ADD PARTITION (PARTITION p3 VALUES LESS THAN (2000));

С таблицами, которые делятся диапазоном, можно использовать ADD PARTITION чтобы добавить новые разделы к верхнему уровню разделов перечисляют только. Попытка добавить новый раздел этим способом между или перед существующими результатами разделов по ошибке как показано здесь:

mysql> ALTER TABLE members     >     ADD PARTITION (     >     PARTITION
        n VALUES LESS THAN (1960));ERROR 1463 (HY000): VALUES LESS THAN value must be strictly »   increasing for each partition

Можно работать вокруг этой проблемы, реорганизовывая первый раздел в два новых, которые разделяют диапазон между ними, как это:

ALTER TABLE members    REORGANIZE PARTITION p0 INTO (        PARTITION n0 VALUES LESS THAN (1960),        PARTITION n1 VALUES LESS THAN (1970));

Используя SHOW CREATE TABLE можно видеть что ALTER TABLE оператор имел требуемый эффект:

mysql> SHOW CREATE TABLE members\G*************************** 1. row ***************************       Table: membersCreate Table: CREATE TABLE `members` (  `id` int(11) DEFAULT NULL,  `fname` varchar(25) DEFAULT NULL,  `lname` varchar(25) DEFAULT NULL,  `dob` date DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1/*!50100 PARTITION BY RANGE ( YEAR(dob))(PARTITION n0 VALUES LESS THAN (1960) ENGINE = InnoDB, PARTITION n1 VALUES LESS THAN (1970) ENGINE = InnoDB, PARTITION p1 VALUES LESS THAN (1980) ENGINE = InnoDB, PARTITION p2 VALUES LESS THAN (1990) ENGINE = InnoDB, PARTITION p3 VALUES LESS THAN (2000) ENGINE = InnoDB) */1 row in set (0.00 sec)

См. также Раздел 13.1.6.1,"ALTER TABLE Операции раздела".

Можно также использовать ALTER TABLE ... ADD PARTITION добавить новые разделы к таблице, которая делится LIST. Предположите таблицу tt определяется, используя следующий CREATE TABLE оператор:

CREATE TABLE tt (    id INT,    data INT)PARTITION BY LIST(data) (    PARTITION p0 VALUES IN (5, 10, 15),    PARTITION p1 VALUES IN (6, 12, 18));

Можно добавить новый раздел, в котором можно сохранить строки, имеющие data значения столбцов 7, 14, и 21 как показано:

ALTER TABLE tt ADD PARTITION (PARTITION p2 VALUES IN (7, 14, 21));

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

mysql> ALTER TABLE tt ADD PARTITION      >     (PARTITION np VALUES IN (4, 8, 12));ERROR 1465 (HY000): Multiple definition of same constant »                    in list partitioning

Поскольку любые строки с data значение столбца 12 были уже присвоены разделить p1, невозможно создать новый раздел на таблице tt это включает 12 в его списке значения. Чтобы выполнить это, Вы могли отбросить p1, и добавьте np и затем новое p1 с измененным определением. Однако, как обсуждено ранее, это привело бы к потере всех данных, хранивших в p1— и это часто имеет место, что это не то, что Вы действительно хотите сделать. Другое решение, могло бы казаться, было бы, чтобы сделать копию таблицы с новым разделением и скопировать данные в это использование CREATE TABLE ... SELECT ..., тогда отбросьте старую таблицу и переименуйте новый, но это могло быть очень отнимающим много времени, имея дело с большие объемы данных. Это также не могло бы быть выполнимо в ситуациях, где высокая доступность является требованием.

Можно добавить многократные разделы в сингле ALTER TABLE ... ADD PARTITION оператор как показано здесь:

CREATE TABLE employees (  id INT NOT NULL,  fname VARCHAR(50) NOT NULL,  lname VARCHAR(50) NOT NULL,  hired DATE NOT NULL)PARTITION BY RANGE( YEAR(hired) ) (  PARTITION p1 VALUES LESS THAN (1991),  PARTITION p2 VALUES LESS THAN (1996),  PARTITION p3 VALUES LESS THAN (2001),  PARTITION p4 VALUES LESS THAN (2005));ALTER TABLE employees ADD PARTITION (    PARTITION p5 VALUES LESS THAN (2010),    PARTITION p6 VALUES LESS THAN MAXVALUE);

К счастью, реализация разделения MySQL обеспечивает способы пересмотреть разделы, не теряя данные. Давайте смотреть сначала на несколько простых включений в качестве примера RANGE разделение. Вспомните members таблица, которая теперь определяется как показано здесь:

mysql> SHOW CREATE TABLE members\G*************************** 1. row ***************************       Table: membersCreate Table: CREATE TABLE `members` (  `id` int(11) default NULL,  `fname` varchar(25) default NULL,  `lname` varchar(25) default NULL,  `dob` date default NULL) ENGINE=MyISAM DEFAULT CHARSET=latin1PARTITION BY RANGE ( YEAR(dob) ) (  PARTITION p0 VALUES LESS THAN (1970) ENGINE = MyISAM,  PARTITION p1 VALUES LESS THAN (1980) ENGINE = MyISAM,  PARTITION p2 VALUES LESS THAN (1990) ENGINE = MyISAM.  PARTITION p3 VALUES LESS THAN (2000) ENGINE = MyISAM)

Предположите, что требуется переместить все элементы представления строк, перенесенные до 1960 в отдельный раздел. Как мы уже видели, это не может быть сделано, используя ALTER TABLE ... ADD PARTITION. Однако, можно использовать другое связанное с разделом расширение ALTER TABLE выполнять это:

ALTER TABLE members REORGANIZE PARTITION p0 INTO (    PARTITION s0 VALUES LESS THAN (1960),    PARTITION s1 VALUES LESS THAN (1970));

В действительности эта команда разделяет раздел p0 в два новых раздела s0 и s1. Это также перемещает данные, которые хранились в p0 в новые разделы согласно правилам, воплощенным в двух PARTITION ... VALUES ... пункты, так, чтобы s0 содержит только те записи для который YEAR(dob) меньше чем 1960 и s1 содержит те строки в который YEAR(dob) больше чем или равен 1960, но меньше чем 1970.

A REORGANIZE PARTITION пункт может также использоваться для того, чтобы объединить смежные разделы. Можно возвратиться members таблица к ее предыдущему разделению как показано здесь:

ALTER TABLE members REORGANIZE PARTITION s0,s1 INTO (    PARTITION p0 VALUES LESS THAN (1970));

Никакие данные не теряются в разделении или слиянии использования разделов REORGANIZE PARTITION. В выполнении вышеупомянутого оператора MySQL перемещает все записи, которые были сохранены в разделах s0 и s1 в раздел p0.

Общий синтаксис для REORGANIZE PARTITION показывается здесь:

ALTER TABLE tbl_name    REORGANIZE PARTITION partition_list    INTO (partition_definitions);

Здесь, tbl_name имя разделенной таблицы, и partition_list список разделенных запятой значений имен одного или более существующих разделов, которые будут изменены. partition_definitions список разделенных запятой значений новых определений раздела, которые следуют за теми же самыми правилами что касается partition_definitions список, используемый в CREATE TABLE (см. Раздел 13.1.14,"CREATE TABLE Синтаксис"). Нужно отметить, что Вы не ограничиваетесь слиянием нескольких разделов в одного, или к разделению одного раздела во многих, при использовании REORGANIZE PARTITION. Например, можно реорганизовать все четыре раздела members таблица в два, следующим образом:

ALTER TABLE members REORGANIZE PARTITION p0,p1,p2,p3 INTO (    PARTITION m0 VALUES LESS THAN (1980),    PARTITION m1 VALUES LESS THAN (2000));

Можно также использовать REORGANIZE PARTITION с таблицами, которые делятся LIST. Давайте возвратимся к проблеме добавления нового раздела к разделенному списком tt таблица и сбой, потому что у нового раздела было значение, которое уже присутствовало в списке значения одного из существующих разделов. Мы можем обработать это, добавляя раздел, который содержит только неконфликтные значения, и затем реорганизацию нового раздела и существующего так, чтобы значение, которое было сохранено в существующем, было теперь перемещено в новый:

ALTER TABLE tt ADD PARTITION (PARTITION np VALUES IN (4, 8));ALTER TABLE tt REORGANIZE PARTITION p1,np INTO (    PARTITION p1 VALUES IN (6, 18),    PARTITION np VALUES in (4, 8, 12));

Вот некоторые ключевые пункты, чтобы иметь в виду при использовании ALTER TABLE ... REORGANIZE PARTITION повторно разделить таблицы, которые делятся RANGE или LIST: