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