常量和列值之间的比较,其中常量值超出范围或相对于列类型的类型错误现在在查询优化期间处理一次,而不是在执行期间逐行处理。可以用这种方式处理的比较有
>
, >=
,
<
, <=
,
<>
/ !=
,
=
, 和<=>
。
考虑由以下语句创建的表:
CREATE TABLE t (c TINYINT UNSIGNED NOT NULL);
WHERE
查询
中
的条件SELECT * FROM t WHERE c < 256
包含超出
TINYINT UNSIGNED
列范围的整数常量 256。以前,这是通过将两个操作数都视为较大的类型来处理的,但现在,由于任何允许的值c
都小于常量,因此WHERE
可以将表达式折叠为WHERE 1
,以便将查询重写为SELECT * FROM t WHERE
1
。
这使得优化器可以
WHERE
完全删除表达式。如果该列
c
可以为空(即,仅定义为
TINYINT UNSIGNED
),则查询将重写如下:
SELECT * FROM t WHERE ti IS NOT NULL
与支持的 MySQL 列类型相比,对常量执行折叠,如下所示:
整数列类型。 整数类型与以下类型的常量进行比较,如下所述:
整数值。 如果常量超出列类型的范围,则比较折叠为
1
orIS 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,然后作为 .01 处理DECIMAL
。字符串类型。 尝试将字符串值解释为整数类型,然后处理整数值之间的比较。如果失败,请尝试将值作为
REAL
.
DECIMAL 或 REAL 列。 十进制类型与以下类型的常量进行比较,如下所述:
整数值。 针对列值的整数部分执行范围检查。如果没有折叠结果,则将常量转换
DECIMAL
为与列值具有相同小数位数的小数位数,然后将其检查为DECIMAL
(见下文)。DECIMAL 或 REAL 值。 检查溢出(即常量的整数部分中的位数是否多于列的小数类型所允许的位数)。如果是这样,弃牌。
如果常量的有效小数位数多于列的类型,则截断该常量。如果比较运算符是
=
or<>
,则折叠。如果运算符是>=
或<=
,则由于截断而调整运算符。例如,如果列的类型是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
日期或时间类型的列或列。在准备语句的准备阶段,虽然它可以在准备语句实际执行时的优化阶段应用。这是因为在语句准备期间,常量的值尚不清楚。