• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 恒定折叠优化

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

    考虑以下语句创建的表:

    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列类型相比,对常量的折叠如下:

    • 整数列类型。如此处所述,将整数类型与以下类型的常量进行比较:

      • 整数值。如果常量超出列类型的范围,则比较将折叠为1IS 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
                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)
        
      • 浮点或定点值。如果常数是十进制类型之一(例如DECIMALREALDOUBLE,或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小数,则截断并在折叠期间进行补偿。对于=<>比较,倍至TRUEFALSEIS[NOT] NULL如前文所述;对于其他操作员,请调整操作员。

      如果该值具有多个m整数,请折叠。

    局限性。在以下情况下不能使用此优化:

    1. 使用BETWEEN或比较IN
    2. 使用BIT列或使用日期或时间类型的列。
    3. 在准备好的语句的准备阶段,尽管它可以在实际执行准备好的语句的优化阶段应用。这是由于以下事实:在语句准备期间,常数的值尚不清楚。

    上篇:条件过滤

    下篇:IS NULL优化