暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

[ACDU翻译]8.2.1.14恒定折叠优化

原创 由迪 2021-04-08
263

现在,常量和列值之间的比较(其中常量值超出范围或相对于列类型而言是错误的类型)现在在查询优化期间而不是逐行而不是在执行期间进行一次处理。可以以这种方式处理的比较是 >,>=, <,<=, <>/ !=, =和<=>。

考虑以下语句创建的表:

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列或使用日期或时间类型的列。

在准备好的语句的准备阶段,尽管它可以在优化阶段实际执行准备好的语句时应用。这是由于以下事实:在语句准备期间,常数的值尚不清楚。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论