Spec-Zone.ru › MySQL 9.2

10.2.1.14 Оптимизация свёртки констант

Сравнения между константами и значениями столбцов, в которых значение константы находится вне диапазона или имеет неверный тип по отношению к типу столбца, теперь обрабатываются один раз во время оптимизации запроса, а не построчно, как во время выполнения. Сравнения, которые могут быть обработаны таким образом, это >, >=, <, <=, <>/!=, = и <=>.

Рассмотрим таблицу, созданную следующим оператором:

CREATE TABLE t (c TINYINT UNSIGNED NOT NULL);

Условие WHERE в запросе SELECT * FROM t WHERE c < 256 содержит целую константу 256, которая находится вне диапазона для столбца TINYINT UNSIGNED. Ранее это обрабатывалось путём обработки обоих операндов как типа большего размера, но теперь, так как любое допустимое значение для c меньше константы, выражение WHERE может быть свёрнуто как WHERE 1, так что запрос переписывается как SELECT * FROM t WHERE 1.

Это позволяет оптимизатору удалить выражение WHERE полностью. Если столбец c был бы nullable (то есть определён только как TINYINT UNSIGNED), запрос был бы переписан следующим образом:

SELECT * FROM t WHERE ti IS NOT NULL

Свёртка выполняется для констант, сравниваемых со поддерживаемыми типами столбцов MySQL следующим образом:

  • Тип целого столбца. Целочисленные типы сравниваются с константами следующих типов, как описано здесь:

    • Целочисленное значение. Если константа находится вне диапазона для типа столбца, сравнение сворачивается в 1 или IS NOT NULL, как уже показано.

      Если константа является границей диапазона, сравнение сворачивается в =. Например (используя ту же таблицу, что и ранее определена):

      mysql> EXPLAIN SELECT * FROM t WHERE c >= 255;
      *************************** 1. row ***************************
                 id: 1
        select_type: SIMPLE
              table: t
         partitions: NULL
               type: ALL
      possible_keys: NULL
                key: NULL
            key_len: NULL
                ref: NULL
               rows: 5
           filtered: 20.00
              Extra: Using where
      1 row in set, 1 warning (0.00 sec)
      
      mysql> SHOW WARNINGS;
      *************************** 1. row ***************************
        Level: Note
         Code: 1003
      Message: /* select#1 */ select `test`.`t`.`ti` AS `ti` from `test`.`t` where (`test`.`t`.`ti` = 255)
      1 row in set (0.00 sec)
      
    • Значение с плавающей или фиксированной точкой. Если константа является одним из десятичных типов (таких как DECIMAL, REAL, DOUBLE или FLOAT) и имеет ненулевую дробную часть, она не может быть равна; сворачивать соответственно. Для других сравнений округлять вверх или вниз до целого значения в соответствии со знаком, затем выполнять проверку диапазона и обрабатывать, как уже описано для сравнений целое-целое.

      Значение REAL, которое слишком мало для представления как DECIMAL, округляется до .01 или -.01 в зависимости от знака, затем обрабатывается как DECIMAL.

    • Строковые типы. Попытаться интерпретировать строковое значение как целочисленный тип, затем обработать сравнение как между целочисленными значениями. Если это не удаётся, попытаться обработать значение как REAL.

  • Столбец DECIMAL или REAL. Десятичные типы сравниваются с константами следующих типов, как описано здесь:

    • Целочисленное значение. Выполнить проверку диапазона по отношению к целочисленной части значения столбца. Если свёртка не даёт результата, преобразовать константу в DECIMAL с тем же числом десятичных знаков, что и у значения столбца, а затем проверить её как DECIMAL (см. следующий пункт).

    • Значение DECIMAL или REAL. Проверить переполнение (то есть, имеет ли константа больше цифр в целой части, чем разрешено для десятичного типа столбца). Если да, сворачивать.

      Если константа имеет больше значимых дробных цифр, чем тип столбца, обрезать константу. Если оператор сравнения это = или <>, сворачивать. Если оператор это >= или <=, скорректировать оператор из-за усечения. Например, если тип столбца DECIMAL(3,1), SELECT * FROM t WHERE f >= 10.13 становится SELECT * FROM t WHERE f > 10.1.

      Если константа имеет меньше десятичных цифр, чем тип столбца, преобразовать её в константу с тем же количеством цифр. Для переполнения значения REAL (то есть, слишком мало дробных цифр для его представления), преобразовать константу в десятичную 0.

    • Строковое значение. Если значение может быть интерпретировано как целочисленный тип, обработать его как таковой. В противном случае, попытаться обработать его как REAL.

  • Столбец FLOAT или DOUBLE. Значения FLOAT(m,n) или DOUBLE(m,n), сравниваемые с константами, обрабатываются следующим образом:

    Если значение выходит за пределы диапазона столбца, сворачивать.

    Если значение имеет более чем n десятичных знаков, усекать, компенсируя при свёртке. Для сравнений = и <> сворачивать в TRUE, FALSE или IS [NOT] NULL, как описано ранее; для других операторов корректировать оператор.

    Если значение имеет более чем m целых цифр, сворачивать.

Ограничения. Эта оптимизация не может быть использована в следующих случаях:

  1. При сравнениях с использованием BETWEEN или IN.

  2. С BIT столбцами или столбцами, использующими типы даты или времени.

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

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

Spec-Zone.ru

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