MySQL查询优化器--逻辑查询优化技术(二)--子查询优化(四)

来源:互联网 发布:js遍历json二维数组 编辑:程序博客网 时间:2024/05/17 08:29

5 MySQL支持的子查询可优化类型

 

从句式的形式看,子查询分为特殊格式子查询和非特殊格式子查询,特殊格式的子查询中又包括INALLANYSOMEEXISTS等类型的子查询,对于有的类型的子查询,MySQL有的支持优化,有的不支持,具体情况如下。

 

示例一,MySQL不支持对EXISTS类型的子查询的优化:

EXISTS类型的相关子查询,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHEREt1.a1= t2.a2 AND t2.a2>10);

+----+--------------------+-------+------+------+-------------+

| id | select_type       | table | type | key  | Extra       |

+----+--------------------+-------+------+------+-------------+

|  1 | PRIMARY            | t1    | ALL | NULL | Using where |

|  2 | DEPENDENT SUBQUERY | t2    | ALL | NULL | Using where |

+----+--------------------+-------+------+------+-------------+

2 rows in set, 2 warnings (0.00 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`,

    `test`.`t1`.`b1` AS `b1`

from`test`.`t1`

whereexists(/* select#2 */

    select 1

    from `test`.`t2`

    where ((`test`.`t1`.`a1` =`test`.`t2`.`a2`) and (`test`.`t2`.`a2` > 10))

)

从查询执行计划看,子查询存在,MySQL没有进一步做子查询的优化工作。

另外的一个EXISTS类型的相关子查询,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHEREt1.b1= t2.b2 AND t1.a1=10);

+----+--------------------+-------+------+------+-------------+

| id | select_type       | table | type | key  | Extra       |

+----+--------------------+-------+------+------+-------------+

|  1 |PRIMARY            | t1    | ALL | NULL | Using where |

|  2 | DEPENDENT SUBQUERY | t2    | ALL | NULL | Using where |

+----+--------------------+-------+------+------+-------------+

2 rows in set, 3 warnings (0.02 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`,

    `test`.`t1`.`b1` AS `b1`

from`test`.`t1`

whereexists(/* select#2 */

    select 1

    from `test`.`t2`

    where ((`test`.`t1`.`b1` =`test`.`t2`.`b2`) and (`test`.`t1`.`a1` = 10))

)

从查询执行计划看,子查询存在,MySQL没有进一步做子查询的优化工作。

 

示例二,MySQL不支持对NOT EXISTS类型的子查询的优化:

NOT EXISTS类型的相关子查询,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE NOT EXISTS(SELECT 1 FROM t2 WHERE t1.a1= t2.a2 AND t2.a2>10);

+----+--------------------+-------+------+------+-------------+

| id | select_type       | table | type | key  | Extra       |

+----+--------------------+-------+------+------+-------------+

|  1 |PRIMARY            | t1    | ALL | NULL | Using where |

|  2 | DEPENDENT SUBQUERY | t2    | ALL | NULL | Using where |

+----+--------------------+-------+------+------+-------------+

2 rows in set, 2 warnings (0.00 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`,

    `test`.`t1`.`b1` AS `b1`

from`test`.`t1`

where (not(exists(

    /* select#2 */ select 1

    from `test`.`t2`

    where ((`test`.`t1`.`a1` =`test`.`t2`.`a2`) and (`test`.`t2`.`a2` > 10))))

)

从查询执行计划看,子查询存在,MySQL没有进一步做子查询的优化工作。

 

另外的一个NOT EXISTS类型的相关子查询,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE NOT EXISTS (SELECT 1 FROM t2 WHEREt1.b1= t2.b2 AND t1.a1=10);

+----+--------------------+-------+------+------+-------------+

| id | select_type       | table | type | key  | Extra       |

+----+--------------------+-------+------+------+-------------+

|  1 |PRIMARY            | t1    | ALL | NULL | Using where |

|  2 | DEPENDENT SUBQUERY | t2    | ALL  | NULL | Using where |

+----+--------------------+-------+------+------+-------------+

2 rows in set, 3 warnings (0.00 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`,

    `test`.`t1`.`b1` AS `b1`

from`test`.`t1`

where (not(exists(

    /* select#2 */ select 1

    from `test`.`t2`

    where ((`test`.`t1`.`b1` =`test`.`t2`.`b2`) and (`test`.`t1`.`a1` = 10))))

)

从查询执行计划看,子查询存在,MySQL没有进一步做子查询的优化工作。

 

示例三,MySQL支持对IN类型的子查询的优化,按也有不支持的情况存在:

IN非相关子查询,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 IN (SELECT a2 FROM t2 WHEREt2.a2>10);

+----+--------------+-------------+------+------+----------------------------------------------------+

| id | select_type | table       | type | key  | Extra  |

+----+--------------+-------------+------+------+----------------------------------------------------+

|  1 | SIMPLE       | <subquery2> | ALL  | NULL | NULL   |

|  1 | SIMPLE       | t1          | ALL | NULL | Using where; Using join buffer (Block Nested Loop) |

|  2 | MATERIALIZED | t2          | ALL | NULL | Using where   |

+----+--------------+-------------+------+------+----------------------------------------------------+

3 rows in set, 1 warning (0.00 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`,

    `test`.`t1`.`b1` AS `b1`

from`test`.`t1` semi join(`test`.`t2`)

where((`test`.`t1`.`a1` = `<subquery2>`.`a2`) and (`test`.`t2`.`a2` > 10))

从查询执行计划看,表t2被物化后,与表t1执行了半连接(semi join)。尽管有“subquery2”这样的内容看起来是子查询,但是表t2已经被上拉到表t1层执行了半连接,所以MySQL支持IN子查询优化为半连接操作。

 

另外一个IN非相关子查询,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 IN (SELECT a2 FROM t2 WHEREt2.a2=10);

+----+--------------+-------------+------+------+----------------------------------------------------+

| id | select_type | table       | type | key  | Extra  |

+----+--------------+-------------+------+------+----------------------------------------------------+

|  1 | SIMPLE       | <subquery2> | ALL  | NULL | Using where   |

|  1 | SIMPLE       | t1          | ALL | NULL | Using where; Using join buffer (BlockNested Loop) |

|  2 | MATERIALIZED | t2          | ALL | NULL | Using where   |

+----+--------------+-------------+------+------+----------------------------------------------------+

3 rows in set, 1 warning (0.02 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`,

    `test`.`t1`.`b1` AS `b1`

from`test`.`t1` semi join(`test`.`t2`)

where((`<subquery2>`.`a2` = 10) and (`test`.`t1`.`a1` = 10) and(`test`.`t2`.`a2` = 10))

从查询执行计划看,子查询不存在,表t1t2直接做了块嵌套循环半连接(Block Nested Loop),把子查询上拉到父查询中用嵌套循环半连接完成IN操作。另外,由于子查询上拉,使得增加连接条件“a1=a2”,而原先的条件“a2=10”可以利用常量传递优化技术,使得“a1=a2=10”,所以查询执行计划中,两个索引扫描的条件分别为:a1 = 10a2 = 10

 

另外一个IN非相关子查询,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 IN (SELECT a2 FROM t2 WHEREt1.a1=10);

+----+-------------+-------+------+------------------------------------------------------------------+

| id | select_type | table | type | Extra           |

+----+-------------+-------+------+------------------------------------------------------------------+

|  1 | SIMPLE      | t2   | ALL  | Using where; Starttemporary           |

|  1 | SIMPLE      | t1   | ALL  | Using where; Endtemporary; Using join buffer (BlockNested Loop)|

+----+-------------+-------+------+------------------------------------------------------------------+

2 rows in set, 2 warnings (0.00 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`,

    `test`.`t1`.`b1` AS `b1`

from`test`.`t1` semi join(`test`.`t2`)

where((`test`.`t2`.`a2` = 10) and (`test`.`t1`.`a1` = 10))

从查询执行计划看,子子查询不存在,表t1t2直接做了块嵌套循环连接(Block Nested Loop),但属于半连接操作(semi join),把子查询上拉到父查询中用嵌套循环半连接完成IN操作。

 

示例四,MySQL支持对NOT IN类型的子查询的优化

NOT IN非相关子查询,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 NOT IN (SELECT a2 FROM t2 WHEREt2.a2>10);

+----+-------------+-------+------+------+-------------+

| id | select_type | table | type | key  | Extra      |

+----+-------------+-------+------+------+-------------+

|  1 |PRIMARY     | t1    | ALL | NULL | Using where |

|  2 | SUBQUERY    | t2   | ALL  | NULL | Using where |

+----+-------------+-------+------+------+-------------+

2 rows in set, 1 warning (0.02 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`,

`test`.`t1`.`b1`AS `b1`

from`test`.`t1`

where (not(<in_optimizer>(

    `test`.`t1`.`a1`,`test`.`t1`.`a1` in (

        <materialize>(/* select#2 */

            select `test`.`t2`.`a2`

            from `test`.`t2`

            where (`test`.`t2`.`a2` > 10)

            having 1

        ),

        <primary_index_lookup>(

            `test`.`t1`.`a1` in <temporarytable> on <auto_key>

            where ((`test`.`t1`.`a1` =`materialized-subquery`.`a2`))

        )

     )

    ))

)

从查询执行计划看,表t2做了子查询(SUBQUERY)。而子查询被物化(materialize)。所以,MySQL对于NOT IN子查询采用了物化的优化方式,但不支持子查询的消除。

 

另外一个NOT IN非相关子查询,查询执行计划如下:

mysql> EXPLAIN EXTENDEDSELECT * FROM t1 WHERE t1.a1 NOT IN (SELECT a2 FROM t2 WHERE t2.a2=10);

+----+-------------+-------+------+------+-------------+

| id | select_type | table |type | key  | Extra       |

+----+-------------+-------+------+------+-------------+

|  1 | PRIMARY     | t1   | ALL  | NULL | Using where |

|  2 | SUBQUERY    | t2   | ALL  | NULL | Using where |

+----+-------------+-------+------+------+-------------+

2 rows in set, 1 warning(0.00 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS`a1`,`test`.`t1`.`b1` AS `b1`

from`test`.`t1`

where (not(<in_optimizer>(

    `test`.`t1`.`a1`,`test`.`t1`.`a1` in (

        <materialize>(/* select#2 */

            select `test`.`t2`.`a2`

            from `test`.`t2`

            where (`test`.`t2`.`a2` = 10)

            having 1

        ),

        <primary_index_lookup>(

            `test`.`t1`.`a1` in <temporarytable> on <auto_key>

            where ((`test`.`t1`.`a1` =`materialized-subquery`.`a2`))

        )

    )

    ))

)

从查询执行计划看,表t2做了子查询(SUBQUERY)。而子查询被物化(materialize)。所以,MySQL对于NOT IN子查询采用了物化的优化方式,但不支持子查询的消除。

 

示例五,MySQL支持对ALL类型的子查询的优化:

不相关的ALL子查询,查询执行计划如下:

mysql>EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 >ALL(SELECT a2 FROM t2 WHERE t2.a2>10);

+----+-------------+-------+------+------+-------------+

| id |select_type | table | type | key  |Extra       |

+----+-------------+-------+------+------+-------------+

|  1 | PRIMARY     | t1   | ALL  | NULL | Using where |

|  2 | SUBQUERY    | t2   | ALL  | NULL | Using where |

+----+-------------+-------+------+------+-------------+

2 rowsin set, 1 warning (0.00 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS`a1`,`test`.`t1`.`b1` AS `b1`

from`test`.`t1`

where<not>((`test`.`t1`.`a1` <=<max>(

    /* select#2 */

    select `test`.`t2`.`a2`

    from `test`.`t2`

    where (`test`.`t2`.`a2` > 10)

    )

))

从查询执行计划看,出现了子查询(SUBQUERY),但是,子查询被“<= <max>”操作符限制,而子查询中的被查询列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“>ALL”式的子查询优化,子查询只被执行一次即可求得最大值。

 

不相关的ALL子查询,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 =ALL (SELECT a2 FROM t2 WHEREt2.a2=10);

+----+--------------------+-------+------+------+-------------+

| id | select_type       | table | type | key  | Extra       |

+----+--------------------+-------+------+------+-------------+

|  1 |PRIMARY            | t1    | ALL | NULL | Using where |

|  2 | DEPENDENT SUBQUERY | t2    | ALL | NULL | Using where |

+----+--------------------+-------+------+------+-------------+

2 rows in set, 1 warning (0.00 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS`a1`,`test`.`t1`.`b1` AS `b1`

from`test`.`t1`

where <not>(<in_optimizer>(

    `test`.`t1`.`a1`,<exists>(

        /* select#2 */ select 1 from`test`.`t2`

        where ((`test`.`t2`.`a2` = 10) and

            <if>(outer_field_is_not_null,

               ((<cache>(`test`.`t1`.`a1`) <> 10) or<cache>(isnull(10))),

                true

            )

        )

        having<if>(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`a2`),true)

    )

))

从查询执行计划看,出现了子查询(SUBQUERY),但是被查询优化器处理后的语句中包含“exists”,这表明MySQL对于“=ALL”式的子查询优化用“EXISTS strategy”方式优化,所以MySQL支持“=ALL”式的子查询优化。

 

不相关的ALL子查询,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 <ALL (SELECT a2 FROM t2 WHEREt2.a2=10);

+----+-------------+-------+------+------+-------------+

| id | select_type | table | type | key  | Extra      |

+----+-------------+-------+------+------+-------------+

|  1 |PRIMARY     | t1    | ALL | NULL | Using where |

|  2 | SUBQUERY    | t2   | ALL  | NULL | Using where |

+----+-------------+-------+------+------+-------------+

2 rows in set, 1 warning (0.00 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS`a1`,`test`.`t1`.`b1` AS `b1`

from`test`.`t1`

where<not>((`test`.`t1`.`a1` >=<min>

    (/* select#2 */

        select `test`.`t2`.`a2`

        from `test`.`t2`

        where (`test`.`t2`.`a2` = 10)

    )

))

从查询执行计划看,出现了子查询(SUBQUERY),但是,子查询被“>= <min>”操作符限制,而子查询中的被查询列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“<ALL”式的子查询优化,子查询只被执行一次即可求得最小值。

 

示例六,MySQL支持对SOME类型的子查询的优化:

使用了“>SOME”式子的子查询被优化,查询执行计划如下:

mysql>EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 >SOME(SELECT a2 FROM t2 WHERE t2.a2>10);

+----+-------------+-------+------+------+-------------+

| id |select_type | table | type | key  |Extra       |

+----+-------------+-------+------+------+-------------+

|  1 | PRIMARY     | t1   | ALL  | NULL | Using where |

|  2 | SUBQUERY    | t2   | ALL  | NULL | Using where |

+----+-------------+-------+------+------+-------------+

2 rowsin set, 1 warning (0.05 sec)

被查询优化器处理后的语句为:

 /* select#1 */ select `test`.`t1`.`id1` AS`id1`,`test`.`t1`.`a1` AS `a1`,

     `test`.`t1`.`b1` AS `b1`

from`test`.`t1`

where<nop>((`test`.`t1`.`a1` > (

    /* select#2 */

    select min(`test`.`t2`.`a2`)

    from `test`.`t2`

    where (`test`.`t2`.`a2` > 10)

)))

从查询执行计划看,出现了子查询(SUBQUERY),但是,子查询被“min”函数限制,而子查询中的被查询列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“>SOME”式的子查询优化,子查询只被执行一次即可求得最大值。

 

使用了“=SOME”式子的子查询被优化,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 =SOME (SELECT a2 FROM t2 WHEREt2.a2=10);

+----+--------------+-------------+------+------+----------------------------------------------------+

| id | select_type | table       | type | key  | Extra  |

+----+--------------+-------------+------+------+----------------------------------------------------+

|  1 | SIMPLE       | <subquery2> | ALL  | NULL | Using where   |

|  1 | SIMPLE       | t1          | ALL | NULL | Using where; Using join buffer (Block Nested Loop) |

|  2 | MATERIALIZED | t2          | ALL | NULL | Using where   |

+----+--------------+-------------+------+------+----------------------------------------------------+

3 rows in set, 1 warning (0.01 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`,

`test`.`t1`.`b1` AS `b1`

from`test`.`t1` semi join(`test`.`t2`)

where((`<subquery2>`.`a2` = 10) and (`test`.`t1`.`a1` = 10) and(`test`.`t2`.`a2` = 10))

从查询执行计划看,没有出现了子查询,表t2被物化,与表t1进行了半连接。

 

使用了“<SOME”式子的子查询被优化,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 <SOME (SELECT a2 FROM t2 WHEREt2.a2=10);

+----+-------------+-------+------+------+-------------+

| id | select_type | table | type | key  | Extra      |

+----+-------------+-------+------+------+-------------+

|  1 |PRIMARY     | t1    | ALL | NULL | Using where |

|  2 | SUBQUERY    | t2   | ALL  | NULL | Using where |

+----+-------------+-------+------+------+-------------+

2 rows in set, 1 warning (0.00 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`,

    `test`.`t1`.`b1` AS `b1`

from`test`.`t1`

where<nop>(

    (

        `test`.`t1`.`a1` < (/* select#2 */

            select max(`test`.`t2`.`a2`)

            from `test`.`t2`

            where (`test`.`t2`.`a2` = 10)

        )

    )

)

从查询执行计划看,出现了子查询(SUBQUERY),但是,子查询被“max”函数限制,而子查询中的被查询列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“<SOME”式的子查询优化,子查询只被执行一次即可求得最大值。

 

示例七,MySQL支持对ANY类型的子查询的优化:

使用了“>ANY”式子的子查询被优化,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 >ANY (SELECT a2 FROM t2 WHEREt2.a2>10);

+----+-------------+-------+------+------+-------------+

| id | select_type | table | type | key  | Extra      |

+----+-------------+-------+------+------+-------------+

|  1 |PRIMARY     | t1    | ALL | NULL | Using where |

|  2 | SUBQUERY    | t2   | ALL  | NULL | Using where |

+----+-------------+-------+------+------+-------------+

2 rows in set, 1 warning (0.00 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`,

    `test`.`t1`.`b1` AS `b1`

from`test`.`t1`

where<nop>(

    (

        `test`.`t1`.`a1` >(/* select#2 */

            select min(`test`.`t2`.`a2`)

            from `test`.`t2`

            where (`test`.`t2`.`a2` > 10)

        )

    )

)

从查询执行计划看,出现了子查询(SUBQUERY),但是,子查询被“min”函数限制,而子查询中的被查询列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“>ANY”式的子查询优化,子查询只被执行一次即可求得最小值。

 

使用了“=ANY”式子的子查询被优化,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1=ANY (SELECT a2 FROM t2 WHERE t2.a2>10);

+----+--------------+-------------+------+------+----------------------------------------------------+

| id | select_type | table       | type | key  | Extra  |

+----+--------------+-------------+------+------+----------------------------------------------------+

|  1 | SIMPLE       | <subquery2> | ALL  | NULL | NULL   |

|  1 | SIMPLE       | t1          | ALL | NULL | Using where; Using join buffer (Block Nested Loop) |

|  2 | MATERIALIZED | t2          | ALL | NULL | Using where   |

+----+--------------+-------------+------+------+----------------------------------------------------+

3 rows in set, 1 warning (0.02 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`,

    `test`.`t1`.`b1` AS `b1`

from`test`.`t1` semi join(`test`.`t2`)

where((`test`.`t1`.`a1` = `<subquery2>`.`a2`) and (`test`.`t2`.`a2` > 10))

从查询执行计划看,没有出现了子查询,表t2被物化,与表t1进行了半连接。

 

使用了“<ANY”式子的子查询被优化,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 <ANY (SELECT a2 FROM t2 WHEREt2.a2>10);

+----+-------------+-------+------+------+-------------+

| id | select_type | table | type | key  | Extra      |

+----+-------------+-------+------+------+-------------+

|  1 |PRIMARY     | t1   | ALL  | NULL | Using where |

|  2 | SUBQUERY    | t2   | ALL  | NULL | Using where |

+----+-------------+-------+------+------+-------------+

2 rows in set, 1 warning (0.00 sec)

被查询优化器处理后的语句为:

/*select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`,

    `test`.`t1`.`b1` AS `b1`

from`test`.`t1`

where<nop>(

    (

        `test`.`t1`.`a1` <(/* select#2 */

            select max(`test`.`t2`.`a2`)

            from `test`.`t2`

            where (`test`.`t2`.`a2` > 10)

        )

    )

)

从查询执行计划看,出现了子查询(SUBQUERY),但是,子查询被“max”函数限制,而子查询中的被查询列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“<ANY”式的子查询优化,子查询只被执行一次即可求得最大值。
0 0