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целых цифр, сворачивать.
Ограничения. Эта оптимизация не может быть использована в следующих случаях:
При сравнениях с использованием
BETWEENилиIN.С
BITстолбцами или столбцами, использующими типы даты или времени.Во время фазы подготовки для подготовленного оператора, хотя она может быть применена в фазе оптимизации, когда подготовленный оператор фактически выполняется. Это связано с тем, что во время подготовки оператора значение константы ещё неизвестно.
© 2025 Oracle
Licensed under the GPLv2 License.