恒定折叠优化
现在,常量和列值之间的比较(其中常量值超出范围或相对于列类型的类型错误)现在在查询优化期间而不是在执行过程中逐行处理一次。可以以这种方式处理的比较是>
,>=
,<
,<=
,<>
/!=
,=
和<=>
。
考虑以下语句创建的表:
CREATE TABLE t (c TINYINTUNSIGNED 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 tWHERE ti IS NOT NULL
与支持的MySQL列类型相比,对常量的折叠如下:
整数列类型。如此处所述,将整数类型与以下类型的常量进行比较:
整数值。如果常量超出列类型的范围,则比较将折叠为
1
或IS NOT NULL
,如已显示。如果常量是范围边界,则将比较折叠到
=
。例如(使用与已定义的表相同的表):mysql>
EXPLAIN SELECT *FROM tWHERE 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 Extr : 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
列或使用日期或时间类型的列。 - 在准备好的语句的准备阶段,尽管它可以在实际执行准备好的语句的优化阶段应用。这是由于以下事实:在语句准备期间,常数的值尚不清楚。