#### 8.2.1.14 恒定折叠优化

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

考虑由以下语句创建的表：

```
CREATE TABLE t (c TINYINT UNSIGNED NOT NULL);
```

这`在哪里`查询中的条件`选择 * 从 t WHERE c < 256`包含超出范围的积分常数 256`TINYINT 未签名`柱子。以前，这是通过将两个操作数都视为较大的类型来处理的，但现在，由于任何允许的值`c`小于常数，则`在哪里`表达式可以改为折叠为`在哪里 1`，因此查询被重写为`选择 * 从 t WHERE 1`.

这使得优化器可以删除`在哪里`完全表达。如果列`c`可以为空（即，仅定义为`TINYINT 未签名`) 查询将被重写如下：

```
SELECT * FROM t WHERE ti IS NOT NULL
```

与支持的 MySQL 列类型相比，对常量执行折叠，如下所示：

-   **整数列类型。**整数类型与以下类型的常量进行比较，如下所述：

    -   **整数值。**如果常量超出列类型的范围，则比较折叠为`1`要么`不为空`，如前所述。

        如果常数是范围边界，则比较折叠为`=`.例如（使用与已定义相同的表）：

        ```
        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)
        ```

    -   **浮点或定点值。**如果常量是十进制类型之一（例如`十进制`,`真实的`,`双倍的`， 要么`漂浮`) 并且有一个非零小数部分，它不能相等；相应地折叠。对于其他比较，根据符号向上或向下舍入为整数值，然后执行范围检查和处理，如整数-整数比较所述。

        一种`真实的`值太小而无法表示为`十进制`根据符号四舍五入为 .01 或 -.01，然后作为`十进制`.

    -   **字符串类型。**尝试将字符串值解释为整数类型，然后将比较处理为整数值之间的比较。如果失败，尝试将值作为`真实的`.

-   **DECIMAL 或 REAL 列。**十进制类型与以下类型的常量进行比较，如下所述：

    -   **整数值。**对列值的整数部分执行范围检查。如果没有折叠结果，则将常量转换为`十进制`具有与列值相同的小数位数，然后将其检查为`十进制`（见下）。

    -   **DECIMAL 或 REAL 值。**检查溢出（即常量在其整数部分的位数是否超过列的十进制类型所允许的位数）。如果是这样，折叠。

        如果常量的有效小数位数比列的类型多，则截断常量。如果比较运算符是`=`要么`<>`， 折叠。如果运营商是`>=`要么`<=`, 因截断而调整算子。例如，如果列的类型是`十进制(3,1)`,`选择 * 从 t WHERE f >= 10.13`变成`选择 * 从 t WHERE f > 10.1`.

        如果常量的小数位数少于列的类型，请将其转换为具有相同位数的常量。对于一个下溢`真实的`值（即小数位数太少而无法表示），将常量转换为十进制 0。

    -   **字符串值。**如果该值可以解释为整数类型，请照此处理。否则，尝试将其处理为`真实的`.

-   **FLOAT 或 DOUBLE 列。**  `漂浮（*`米`*,*`n`*)`要么`双倍的（*`米`*,*`n`*)`与常量比较的值按如下方式处理：

    如果值超出列的范围，则折叠。

    如果值大于*`n`*小数，截断，折叠时补偿。为了`=`和`<>`比较，折叠到`真的`,`错误的`， 要么`是[不] NULL`如前所述；对于其他算子，调整算子。

    如果值大于`米`整数位，折叠。

**限制。**在以下情况下不能使用此优化：

1.  比较使用`之间`要么`在`.

2.  和`少量`使用日期或时间类型的列或列。

3.  在准备好的语句的准备阶段，尽管它可以在实际执行准备好的语句的优化阶段应用。这是因为在语句准备期间，常数的值尚不清楚。
