Comparisons between constants and column values in which the constant value is out of range or of the wrong type with respect to the column type are now handled once during query optimization rather row-by-row than during execution. 如果常量值超出范围或列类型错误,则常量和列值之间的比较现在在查询优化期间处理一次,而不是在执行期间逐行处理。The comparisons that can be treated in this manner are 可以以这种方式处理的比较包括>
, >=
, <
, <=
, <>
/!=
, =
, and <=>
.>
、>=
、<
、<=
、<>
/!=
、=
和<=>
。
Consider the table created by the following statement:考虑以下语句创建的表:
CREATE TABLE t (c TINYINT UNSIGNED NOT NULL);
The 查询WHERE
condition in the query SELECT * FROM t WHERE c < 256
contains the integral constant 256 which is out of range for a TINYINT UNSIGNED
column. SELECT * FROM t WHERE c < 256
中的WHERE
条件包含整数常量256,该常量超出了TINYINT UNSIGNED
列的范围。Previously, this was handled by treating both operands as the larger type, but now, since any allowed value for 以前,这是通过将两个操作数都视为较大的类型来处理的,但现在,由于c
is less than the constant, the WHERE
expression can instead be folded as WHERE 1
, so that the query is rewritten as SELECT * FROM t WHERE 1
.c
的任何允许值都小于常量,因此WHERE
表达式可以折叠为WHERE 1
,以便将查询重写为SELECT * FROM t WHERE 1
。
This makes it possible for the optimizer to remove the 这使得优化器可以完全删除WHERE
expression altogether. WHERE
表达式。If the column 如果列c
were nullable (that is, defined only as TINYINT UNSIGNED
) the query would be rewritten like this:c
可为空(即,仅定义为TINYINT UNSIGNED
),则查询将被重写如下:
SELECT * FROM t WHERE ti IS NOT NULL
Folding is performed for constants compared to supported MySQL column types as follows:与支持的MySQL列类型相比,对常量执行折叠,如下所示:
Integer column type.整数列类型。 Integer types are compared with constants of the following types as described here:整数类型与以下类型的常量进行比较,如下所述:
Integer value.整数值。 If the constant is out of range for the column type, the comparison is folded to 如果常量超出列类型的范围,则比较将折叠为1
or IS NOT NULL
, as already shown.1
或IS NOT NULL
,如前所示。
If the constant is a range boundary, the comparison is folded to 如果常数是范围边界,则比较将折叠为=
. =
。For example (using the same table as already defined):例如(使用与已定义相同的表):
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)
Floating- or fixed-point value.浮点值或定点值。 If the constant is one of the decimal types (such as 如果常量是十进制类型之一(如DECIMAL
, REAL
, DOUBLE
, or FLOAT
) and has a nonzero decimal portion, it cannot be equal; fold accordingly. DECIMAL
、REAL
、DOUBLE
或FLOAT
),并且具有非零的十进制部分,则它不能相等;相应地折叠。For other comparisons, round up or down to an integer value according to the sign, then perform a range check and handle as already described for integer-integer comparisons.对于其他比较,根据符号向上或向下取整为一个整数值,然后执行范围检查和处理,如前面针对整数比较所述。
A 太小而无法表示为十进制的REAL
value that is too small to be represented as DECIMAL
is rounded to .01 or -.01 depending on the sign, then handled as a DECIMAL
.REAL
值根据符号舍入为.01或-.01,然后作为十进制处理。
String types.字符串类型。 Try to interpret the string value as an integer type, then handle the comparison as between integer values. 尝试将字符串值解释为整数类型,然后将比较处理为整数值之间的比较。If this fails, attempt to handle the value as a 如果失败,请尝试将该值作为REAL
.REAL
处理。
DECIMAL or REAL column.十进制或实数列。 Decimal types are compared with constants of the following types as described here:十进制类型与以下类型的常量进行比较,如下所述:
Integer value.整数值。 Perform a range check against the column value's integer part. 对列值的整数部分执行范围检查。If no folding results, convert the constant to 如果没有折叠结果,请将常量转换为与列值具有相同小数位数的DECIMAL
with the same number of decimal places as the column value, then check it as a DECIMAL
(see next).DECIMAL
,然后将其作为DECIMAL
进行检查(请参见下一步)。
DECIMAL or REAL value.十进制或实数。 Check for overflow (that is, whether the constant has more digits in its integer part than allowed for the column's decimal type). 检查溢出(即,常量的整数部分的位数是否超过列的十进制类型所允许的位数)。If so, fold.如果是,请折叠。
If the constant has more significant fractional digits than column's type, truncate the constant. 如果常数的有效小数位数大于列的类型,请截断该常数。If the comparison operator is 如果比较运算符为=
or <>
, fold. =
或<>
,请折叠If the operator is 如果运算符为>=
or <=
, adjust the operator due to truncation. >=
或<=
,由于截断,请调整运算符。For example, if column's type is 例如,如果列的类型为DECIMAL(3,1)
, SELECT * FROM t WHERE f >= 10.13
becomes SELECT * FROM t WHERE f > 10.1
.DECIMAL(3,1)
,则SELECT * FROM t WHERE f >= 10.13
变成了SELECT * FROM t WHERE f > 10.1
。
If the constant has fewer decimal digits than the column's type, convert it to a constant with same number of digits. 如果常量的小数位数少于列的类型,请将其转换为具有相同位数的常量。For underflow of a 对于REAL
value (that is, too few fractional digits to represent it), convert the constant to decimal 0.REAL
值的下溢(即小数位数太少而无法表示),请将常量转换为十进制0。
String value.字符串值。 If the value can be interpreted as an integer type, handle it as such. 如果该值可以解释为整数类型,请将其作为整数类型处理。Otherwise, try to handle it as 否则,试着把它当作REAL
.REAL
。
FLOAT or DOUBLE column.FLOAT列或DOUBLE列 FLOAT(
m
,n
) or 或DOUBLE(
m
,n
)values compared with constants are handled as follows:与常量比较的值处理如下:
If the value overflows the range of the column, fold.如果该值超出列的范围,请折叠。
If the value has more than 如果该值的小数位数超过n
decimals, truncate, compensating during folding. n
,则截断,并在折叠过程中进行补偿。For 对于=
and <>
comparisons, fold to TRUE
, FALSE
, or IS [NOT] NULL
as described previously; for other operators, adjust the operator.=
和<>
比较,如前所述,折叠为TRUE
、FLASE
或IS [NOT] NULL
;对于其他运算符,请调整运算符。
If the value has more than 如果该值的整数位数超过m
integer digits, fold.m
,请折叠。
Limitations.局限性 This optimization cannot be used in the following cases:此优化不能用于以下情况:
With comparisons using 使用BETWEEN
or IN
.BETWEEN
或IN
比较。
With 具有BIT
columns or columns using date or time types.BIT
列或使用日期或时间类型的列。
During the preparation phase for a prepared statement, although it can be applied during the optimization phase when the prepared statement is actually executed. 在准备语句的准备阶段,尽管它可以在实际执行准备语句的优化阶段应用。This due to the fact that, during statement preparation, the value of the constant is not yet known.这是因为在语句准备期间,常数的值还未知。