Spec-Zone.ru › MySQL 9.2

26.2.1 Разбиение по диапазонам

Таблица, разделяемая по диапазонам, разделена таким образом, что каждый раздел содержит строки, для которых значение выражения разделения лежит в заданном диапазоне. Диапазоны должны быть непрерывными, но не перекрывающимися, и определяются с помощью оператора VALUES LESS THAN. В следующих примерах предположим, что вы создаёте таблицу для хранения данных о сотрудниках 20 видеомагазинов, пронумерованных от 1 до 20:

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
);
Примечание

Таблица employees, используемая здесь, не имеет первичных или уникальных ключей. Хотя примеры работают как показано для целей данного обсуждения, вы должны помнить, что на практике таблицы очень вероятно будут иметь первичные ключи, уникальные ключи или оба, и допустимые варианты столбцов разбиения зависят от столбцов, используемых для этих ключей, если таковые имеются. Более подробное обсуждение этих вопросов можно найти в разделе 26.6.1, «Ключи разбиения, первичные ключи и уникальные ключи».

Эту таблицу можно разбить на диапазоны различными способами, в зависимости от ваших потребностей. Одним из способов является использование столбца store_id. Например, вы можете разбить таблицу на 4 части, добавив предложение PARTITION BY RANGE, как показано здесь:

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
)
PARTITION BY RANGE (store_id) (
    PARTITION p0 VALUES LESS THAN (6),
    PARTITION p1 VALUES LESS THAN (11),
    PARTITION p2 VALUES LESS THAN (16),
    PARTITION p3 VALUES LESS THAN (21)
);

В этой схеме разбиения все строки, соответствующие сотрудникам, работающим в магазинах с номерами от 1 до 5, хранятся в разделе p0, сотрудники магазинов с номерами от 6 до 10 хранятся в разделе p1 и так далее. Каждый раздел определяется в порядке от наименьшего к наибольшему. Это требование синтаксиса PARTITION BY RANGE; вы можете рассматривать это как аналогичные инструкции if ... elseif ... в C или Java.

Легко определить, что новая строка с данными (72, 'Mitchell', 'Wilson', '1998-06-25', DEFAULT, 7, 13) вставляется в раздел p2, но что произойдёт, когда ваша сеть добавит 21-й магазин? В рамках этой схемы нет правила, охватывающего строку, у которой значение store_id больше 20, поэтому возникает ошибка, потому что сервер не знает, куда её поместить. Вы можете избежать этого, используя предложение “catchall” VALUES LESS THAN в инструкции 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 NOT NULL,
    store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
    PARTITION p0 VALUES LESS THAN (6),
    PARTITION p1 VALUES LESS THAN (11),
    PARTITION p2 VALUES LESS THAN (16),
    PARTITION p3 VALUES LESS THAN MAXVALUE
);

(Как и в других примерах в этой главе, мы предполагаем, что по умолчанию используется хранилище InnoDB.)

Другим способом избежать ошибки, когда не найдено соответствующее значение, является использование ключевого слова IGNORE как части инструкции INSERT. Пример см. в разделе 26.2.2, «Разбиение по спискам».

MAXVALUE представляет целое число, которое всегда больше наибольшего возможного целого значения (в математической терминологии это наименьшая верхняя граница). Теперь все строки, у которых значение столбца store_id больше или равно 16 (наибольшему определённому значению), хранятся в разделе p3. В будущем — когда число магазинов увеличится до 25, 30 или более — вы можете использовать инструкцию ALTER TABLE, чтобы добавить новые разделы для магазинов 21-25, 26-30 и так далее (подробности об этом см. в разделе 26.3, «Управление разбиениями»).

Аналогичным образом, вы могли бы разбить таблицу на основе кодов должностей сотрудников — то есть, по диапазонам значений столбца job_code. Например, если двухзначные коды используются для обычных (внутримагазинных) работников, трёхзначные — для офисных и вспомогательного персонала, а четырёхзначные — для руководящих должностей, вы могли бы создать разнесённую таблицу с помощью следующей инструкции:

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
)
PARTITION BY RANGE (job_code) (
    PARTITION p0 VALUES LESS THAN (100),
    PARTITION p1 VALUES LESS THAN (1000),
    PARTITION p2 VALUES LESS THAN (10000)
);

В этом случае все строки, относящиеся к внутримагазиным работникам, будут храниться в разделе p0, относящиеся к офисному и вспомогательному персоналу в p1, а относящиеся к руководителям — в разделе p2.

Также можно использовать выражение в предложениях VALUES LESS THAN. Однако MySQL должен иметь возможность вычислить возвращаемое значение выражения в контексте сравнения LESS THAN (<).

Вместо разделения данных таблицы по номерам магазинов, вы можете использовать выражение, основанное на одном из двух столбцов DATE. Например, предположим, что вы хотите разбить таблицу на основе года ухода каждого сотрудника, то есть, значения YEAR(separated). Пример инструкции 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 RANGE ( YEAR(separated) ) (
    PARTITION p0 VALUES LESS THAN (1991),
    PARTITION p1 VALUES LESS THAN (1996),
    PARTITION p2 VALUES LESS THAN (2001),
    PARTITION p3 VALUES LESS THAN MAXVALUE
);

В этой схеме для всех сотрудников, ушедших до 1991 года, строки хранятся в разделе p0; для тех, кто ушел в период с 1991 по 1995 годы, в p1; для тех, кто ушел в период с 1996 по 2000 годы, в p2; и для всех сотрудников, ушедших после 2000 года, в p3.

Также можно разделить таблицу по RANGE, основываясь на значении столбца TIMESTAMP, используя функцию UNIX_TIMESTAMP(), как показано в этом примере:

CREATE TABLE quarterly_report_status (
    report_id INT NOT NULL,
    report_status VARCHAR(20) NOT NULL,
    report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) (
    PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ),
    PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ),
    PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ),
    PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ),
    PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ),
    PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ),
    PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ),
    PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ),
    PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ),
    PARTITION p9 VALUES LESS THAN (MAXVALUE)
);

Любые другие выражения, включающие значения TIMESTAMP, запрещены. (См. ошибку #42849.)

Разбиение по диапазонам особенно полезно, когда выполняется одно или несколько из следующих условий:

  • Вы хотите или должны удалить «старые» данные. Если вы используете схему разбиения, показанную ранее для таблицы employees, вы можете просто использовать ALTER TABLE employees DROP PARTITION p0; для удаления всех строк, относящихся к сотрудникам, которые перестали работать в компании до 1991 года. (См. раздел 15.1.9, «Инструкция ALTER TABLE» и раздел 26.3, «Управление разбиениями» для получения дополнительной информации.) Для таблицы с большим количеством строк это может быть намного эффективнее, чем выполнение запроса DELETE, такого как DELETE FROM employees WHERE YEAR(separated) <= 1990;.

  • Вы хотите использовать столбец, содержащий значения даты или времени, или значения, полученные из другой последовательности.

  • Вы часто выполняете запросы, которые напрямую зависят от столбца, используемого для разбиения таблицы. Например, при выполнении запроса, такого как EXPLAIN SELECT COUNT(*) FROM employees WHERE separated BETWEEN '2000-01-01' AND '2000-12-31' GROUP BY store_id;, MySQL может быстро определить, что необходимо просканировать только раздел p2, потому что оставшиеся разделы не могут содержать записи, удовлетворяющие условию WHERE. Подробнее о том, как это выполняется, см. в разделе 26.4, «Обрезка разбиений».

Вариантом этого типа разбиения является разбиение по RANGE COLUMNS. Разбиение по RANGE COLUMNS позволяет использовать несколько столбцов для определения диапазонов разбиения, которые применяются как к размещению строк в разделах, так и для определения включения или исключения определенных разделов при выполнении обрезки разбиений. Дополнительную информацию см. в разделе 26.2.3.1, «Разбиение по диапазонам столбцов».

Схемы разбиения, основанные на интервалах времени. Если вы хотите реализовать схему разбиения, основанную на диапазонах или интервалах времени в MySQL 9.2, у вас есть два варианта:

  1. Разбейте таблицу по RANGE, а для выражения разбиения используйте функцию, работающую со столбцом DATE, TIME или DATETIME и возвращающую целое значение, как показано здесь:

    CREATE TABLE members (
        firstname VARCHAR(25) NOT NULL,
        lastname VARCHAR(25) NOT NULL,
        username VARCHAR(16) NOT NULL,
        email VARCHAR(35),
        joined DATE NOT NULL
    )
    PARTITION BY RANGE( YEAR(joined) ) (
        PARTITION p0 VALUES LESS THAN (1960),
        PARTITION p1 VALUES LESS THAN (1970),
        PARTITION p2 VALUES LESS THAN (1980),
        PARTITION p3 VALUES LESS THAN (1990),
        PARTITION p4 VALUES LESS THAN MAXVALUE
    );
    

    В MySQL 9.2 также можно разбить таблицу по RANGE, основываясь на значении столбца TIMESTAMP, используя функцию UNIX_TIMESTAMP(), как показано в этом примере:

    CREATE TABLE quarterly_report_status (
        report_id INT NOT NULL,
        report_status VARCHAR(20) NOT NULL,
        report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    )
    PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) (
        PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ),
        PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ),
        PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ),
        PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ),
        PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ),
        PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ),
        PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ),
        PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ),
        PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ),
        PARTITION p9 VALUES LESS THAN (MAXVALUE)
    );
    

    В MySQL 9.2 запрещены любые другие выражения, включающие значения TIMESTAMP. (См. ошибку #42849.)

    Примечание

    В MySQL 9.2 также можно использовать UNIX_TIMESTAMP(timestamp_column) как выражение разбиения для таблиц, разделяемых по LIST. Однако это обычно непрактично.

  2. Разбейте таблицу по RANGE COLUMNS, используя столбец DATE или DATETIME как столбец разбиения. Например, таблицу members можно определить, используя столбец joined напрямую, как показано здесь:

    CREATE TABLE members (
        firstname VARCHAR(25) NOT NULL,
        lastname VARCHAR(25) NOT NULL,
        username VARCHAR(16) NOT NULL,
        email VARCHAR(35),
        joined DATE NOT NULL
    )
    PARTITION BY RANGE COLUMNS(joined) (
        PARTITION p0 VALUES LESS THAN ('1960-01-01'),
        PARTITION p1 VALUES LESS THAN ('1970-01-01'),
        PARTITION p2 VALUES LESS THAN ('1980-01-01'),
        PARTITION p3 VALUES LESS THAN ('1990-01-01'),
        PARTITION p4 VALUES LESS THAN MAXVALUE
    );
    
Примечание

Использование разделяющих столбцов с типами данных даты или времени, отличными от DATE или DATETIME, не поддерживается в RANGE COLUMNS.

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

Spec-Zone.ru

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