Spec-Zone.ru › MySQL 9.2

26.4 Удаление несоответствующих разделов

Оптимизация, известная как удаление несоответствующих разделов, основана на относительно простом понятии, которое можно описать как “Не сканировать разделы, где не может быть совпадающих значений”. Предположим, что таблицу с разбиением t1 создаёт эта команда:

CREATE TABLE t1 (
    fname VARCHAR(50) NOT NULL,
    lname VARCHAR(50) NOT NULL,
    region_code TINYINT UNSIGNED NOT NULL,
    dob DATE NOT NULL
)
PARTITION BY RANGE( region_code ) (
    PARTITION p0 VALUES LESS THAN (64),
    PARTITION p1 VALUES LESS THAN (128),
    PARTITION p2 VALUES LESS THAN (192),
    PARTITION p3 VALUES LESS THAN MAXVALUE
);

Предположим, что вы хотите получить результаты из инструкции SELECT, например такой:

SELECT fname, lname, region_code, dob
    FROM t1
    WHERE region_code > 125 AND region_code < 130;

Легко увидеть, что ни одна из строк, которые должны быть возвращены, не находится ни в одном из разделов p0 или p3; то есть, нам нужно искать только в разделах p1 и p2, чтобы найти соответствующие строки. Ограничивая поиск, можно потратить гораздо меньше времени и усилий на поиск соответствующих строк, чем при сканировании всех разделов в таблице. Это «удаление» ненужных разделов известно как удаление несоответствующих разделов. Когда оптимизатор может использовать удаление несоответствующих разделов при выполнении этого запроса, выполнение запроса может быть на порядок быстрее, чем тот же запрос к неразделённой таблице, содержащей те же определения столбцов и данные.

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

  • partition_column = constant

  • partition_column IN (constant1, constant2, ..., constantN)

В первом случае оптимизатор просто оценивает выражение разбиения для заданного значения, определяет, в каком разделе содержится это значение, и сканирует только этот раздел. Во многих случаях знак равенства можно заменить другим арифметическим сравнением, включая <, >, <=, >= и <>. Некоторые запросы, использующие BETWEEN в предложении WHERE, также могут использовать удаление несоответствующих разделов. См. примеры позже в этом разделе.

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

Инструкции SELECT, DELETE и UPDATE поддерживают удаление несоответствующих разделов. Инструкция INSERT также обращается только к одному разделу на вставленную строку; это верно даже для таблицы, которая разделена по HASH или KEY, хотя это в настоящее время не отображается в выводе инструкции EXPLAIN.

Удаление несоответствующих разделов также может применяться к коротким диапазонам, которые оптимизатор может преобразовать в эквивалентные списки значений. Например, в предыдущем примере предложение WHERE может быть преобразовано в WHERE region_code IN (126, 127, 128, 129). Затем оптимизатор может определить, что первые два значения в списке находятся в разделе p1, оставшиеся два значения — в разделе p2, и что другие разделы не содержат соответствующих значений, и поэтому их не нужно просматривать в поисках соответствующих строк.

Оптимизатор также может выполнить удаление несоответствующих разделов для условий WHERE, которые включают сравнения вышеперечисленных типов по нескольким столбцам для таблиц, использующих разбиение RANGE COLUMNS или LIST COLUMNS.

Этот тип оптимизации может применяться всякий раз, когда выражение разбиения состоит из равенства или диапазона, который можно свести к набору равенств, или когда выражение разбиения представляет возрастающую или убывающую зависимость. Удаление несоответствующих разделов также может применяться к таблицам, разделяемым по столбцу DATE или DATETIME, когда выражение разбиения использует функцию YEAR() или TO_DAYS(). Удаление несоответствующих разделов также может применяться к таким таблицам, когда выражение разбиения использует функцию TO_SECONDS().

Предположим, что таблица t2, разделяемая по столбцу DATE, создаётся с помощью показанной здесь инструкции:

CREATE TABLE t2 (
    fname VARCHAR(50) NOT NULL,
    lname VARCHAR(50) NOT NULL,
    region_code TINYINT UNSIGNED NOT NULL,
    dob DATE NOT NULL
)
PARTITION BY RANGE( YEAR(dob) ) (
    PARTITION d0 VALUES LESS THAN (1970),
    PARTITION d1 VALUES LESS THAN (1975),
    PARTITION d2 VALUES LESS THAN (1980),
    PARTITION d3 VALUES LESS THAN (1985),
    PARTITION d4 VALUES LESS THAN (1990),
    PARTITION d5 VALUES LESS THAN (2000),
    PARTITION d6 VALUES LESS THAN (2005),
    PARTITION d7 VALUES LESS THAN MAXVALUE
);

Следующие инструкции, использующие t2, могут использовать удаление несоответствующих разделов:

SELECT * FROM t2 WHERE dob = '1982-06-23';

UPDATE t2 SET region_code = 8 WHERE dob BETWEEN '1991-02-15' AND '1997-04-25';

DELETE FROM t2 WHERE dob >= '1984-06-21' AND dob <= '1999-06-21'

В случае последней инструкции оптимизатор может также действовать следующим образом:

  1. Найти раздел, содержащий нижний конец диапазона.

    YEAR('1984-06-21') даёт значение 1984, которое находится в разделе d3.

  2. Найти раздел, содержащий верхний конец диапазона.

    YEAR('1999-06-21') вычисляется до 1999, который находится в разделе d5.

  3. Сканировать только эти два раздела и любые разделы, которые могут находиться между ними.

    В этом случае это означает, что сканируются только разделы d3, d4 и d5. Остальные разделы можно безопасно игнорировать (и они игнорируются).

Важно

Недействительные DATE и DATETIME значения, на которые ссылается условие WHERE инструкции по отношению к таблице с разбиением, обрабатываются как NULL. Это означает, что запрос, такой как SELECT * FROM partitioned_table WHERE date_column < '2008-12-00', не возвращает никаких значений (см. баг #40972).

До сих пор мы рассматривали только примеры с использованием разбиения по RANGE, но удаление несоответствующих разделов может применяться и с другими типами разбиений.

Рассмотрим таблицу, которая разделена по LIST, где выражение разбиения возрастает или убывает, например таблицу t3, показанную здесь. (В этом примере для краткости предполагается, что столбец region_code ограничен значениями от 1 до 10 включительно.)

CREATE TABLE t3 (
    fname VARCHAR(50) NOT NULL,
    lname VARCHAR(50) NOT NULL,
    region_code TINYINT UNSIGNED NOT NULL,
    dob DATE NOT NULL
)
PARTITION BY LIST(region_code) (
    PARTITION r0 VALUES IN (1, 3),
    PARTITION r1 VALUES IN (2, 5, 8),
    PARTITION r2 VALUES IN (4, 9),
    PARTITION r3 VALUES IN (6, 7, 10)
);

Для инструкции, такой как SELECT * FROM t3 WHERE region_code BETWEEN 1 AND 3, оптимизатор определяет, в каких разделах находятся значения 1, 2 и 3 (r0 и r1) и пропускает остальные (r2 и r3).

Для таблиц, разделяемых по HASH или [LINEAR] KEY, удаление несоответствующих разделов также возможно в тех случаях, когда предложение WHERE использует простое = отношение по отношению к столбцу, используемому в выражении разбиения. Рассмотрим таблицу, созданную так:

CREATE TABLE t4 (
    fname VARCHAR(50) NOT NULL,
    lname VARCHAR(50) NOT NULL,
    region_code TINYINT UNSIGNED NOT NULL,
    dob DATE NOT NULL
)
PARTITION BY KEY(region_code)
PARTITIONS 8;

Инструкция, сравнивающая значение столбца с константой, может быть удалена:

UPDATE t4 WHERE region_code = 7;

Удаление несоответствующих разделов также может быть применено для коротких диапазонов, поскольку оптимизатор может преобразовать такие условия в IN отношения. Например, используя ту же таблицу t4, определённую ранее, запросы, такие как эти, могут быть удалены:

SELECT * FROM t4 WHERE region_code > 2 AND region_code < 6;

SELECT * FROM t4 WHERE region_code BETWEEN 3 AND 5;

В обоих этих случаях предложение WHERE преобразуется оптимизатором в WHERE region_code IN (3, 4, 5).

Важно

Эта оптимизация используется только в том случае, если размер диапазона меньше, чем количество разделов. Рассмотрим эту инструкцию:

DELETE FROM t4 WHERE region_code BETWEEN 4 AND 12;

Диапазон в предложении WHERE охватывает 9 значений (4, 5, 6, 7, 8, 9, 10, 11, 12), но t4 имеет только 8 разделов. Это означает, что DELETE не может быть удалена.

Когда таблица разделена по HASH или [LINEAR] KEY, удаление несоответствующих разделов может использоваться только для целочисленных столбцов. Например, эта инструкция не может использовать удаление, потому что dob — это столбец DATE:

SELECT * FROM t4 WHERE dob >= '2001-04-14' AND dob <= '2005-10-15';

Однако, если таблица хранит значения года в столбце типа INT, то запрос с WHERE year_col >= 2001 AND year_col <= 2005 может быть удалён.

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

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

Spec-Zone.ru

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