MySQL的子查询及相关优化学习教程
一、子查询
1、where型子查询
(把内层查询结果当作外层查询的比较条件)
#不用orderby来查询最新的商品 selectgoods_id,goods_namefromgoodswheregoods_id=(selectmax(goods_id)fromgoods);
#取出每个栏目下最新的产品(goods_id唯一) selectcat_id,goods_id,goods_namefromgoodswheregoods_idin(selectmax(goods_id)fromgoodsgroupbycat_id);
2、from型子查询
(把内层的查询结果供外层再次查询)
#用子查询查出挂科两门及以上的同学的平均成绩
思路:
#先查出哪些同学挂科两门以上 selectname,count(*)asgkfromstuwherescore<60havinggk>=2; #以上查询结果,我们只要名字就可以了,所以再取一次名字 selectnamefrom(selectname,count(*)asgkfromstuhavinggk>=2)ast; #找出这些同学了,那么再计算他们的平均分 selectname,avg(score)fromstuwherenamein(selectnamefrom(selectname,count(*)asgkfromstuhavinggk>=2)ast)groupbyname;
3、exists型子查询
(把外层查询结果拿到内层,看内层的查询是否成立)
#查询哪些栏目下有商品,栏目表category,商品表goods selectcat_id,cat_namefromcategorywhereexists(select*fromgoodswheregoods.cat_id=category.cat_id);
二、优化
从句式的形式看,子查询分为特殊格式子查询和非特殊格式子查询,特殊格式的子查询中又包括IN、ALL、ANY、SOME、EXISTS等类型的子查询,对于有的类型的子查询,MySQL有的支持优化,有的不支持,具体情况如下。
示例一,MySQL不支持对EXISTS类型的子查询的优化:
EXISTS类型的相关子查询,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREEXISTS(SELECT1FROMt2WHEREt1.a1=t2.a2ANDt2.a2>10);
+----+--------------------+-------+------+------+-------------+ |id|select_type|table|type|key|Extra| +----+--------------------+-------+------+------+-------------+ |1|PRIMARY|t1|ALL|NULL|Usingwhere| |2|DEPENDENTSUBQUERY|t2|ALL|NULL|Usingwhere| +----+--------------------+-------+------+------+-------------+ 2rowsinset,2warnings(0.00sec)
被查询优化器处理后的语句为:
/*select#1*/select`test`.`t1`.`id1`AS`id1`,`test`.`t1`.`a1`AS`a1`, `test`.`t1`.`b1`AS`b1` from`test`.`t1` whereexists(/*select#2*/ select1 from`test`.`t2` where((`test`.`t1`.`a1`=`test`.`t2`.`a2`)and(`test`.`t2`.`a2`>10)) )
从查询执行计划看,子查询存在,MySQL没有进一步做子查询的优化工作。
另外的一个EXISTS类型的相关子查询,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREEXISTS(SELECT1FROMt2WHEREt1.b1=t2.b2ANDt1.a1=10);
+----+--------------------+-------+------+------+-------------+ |id|select_type|table|type|key|Extra| +----+--------------------+-------+------+------+-------------+ |1|PRIMARY|t1|ALL|NULL|Usingwhere| |2|DEPENDENTSUBQUERY|t2|ALL|NULL|Usingwhere| +----+--------------------+-------+------+------+-------------+ 2rowsinset,3warnings(0.02sec)
被查询优化器处理后的语句为:
/*select#1*/select`test`.`t1`.`id1`AS`id1`,`test`.`t1`.`a1`AS`a1`, `test`.`t1`.`b1`AS`b1` from`test`.`t1` whereexists(/*select#2*/ select1 from`test`.`t2` where((`test`.`t1`.`b1`=`test`.`t2`.`b2`)and(`test`.`t1`.`a1`=10)) )
从查询执行计划看,子查询存在,MySQL没有进一步做子查询的优化工作。
示例二,MySQL不支持对NOTEXISTS类型的子查询的优化:
NOTEXISTS类型的相关子查询,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHERENOTEXISTS(SELECT1FROMt2WHEREt1.a1=t2.a2ANDt2.a2>10);
+----+--------------------+-------+------+------+-------------+ |id|select_type|table|type|key|Extra| +----+--------------------+-------+------+------+-------------+ |1|PRIMARY|t1|ALL|NULL|Usingwhere| |2|DEPENDENTSUBQUERY|t2|ALL|NULL|Usingwhere| +----+--------------------+-------+------+------+-------------+ 2rowsinset,2warnings(0.00sec)
被查询优化器处理后的语句为:
/*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*/select1 from`test`.`t2` where((`test`.`t1`.`a1`=`test`.`t2`.`a2`)and(`test`.`t2`.`a2`>10)))) )
从查询执行计划看,子查询存在,MySQL没有进一步做子查询的优化工作。
另外的一个NOTEXISTS类型的相关子查询,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHERENOTEXISTS(SELECT1FROMt2WHEREt1.b1=t2.b2ANDt1.a1=10);
+----+--------------------+-------+------+------+-------------+ |id|select_type|table|type|key|Extra| +----+--------------------+-------+------+------+-------------+ |1|PRIMARY|t1|ALL|NULL|Usingwhere| |2|DEPENDENTSUBQUERY|t2|ALL|NULL|Usingwhere| +----+--------------------+-------+------+------+-------------+ 2rowsinset,3warnings(0.00sec)
被查询优化器处理后的语句为:
/*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*/select1 from`test`.`t2` where((`test`.`t1`.`b1`=`test`.`t2`.`b2`)and(`test`.`t1`.`a1`=10)))) )
从查询执行计划看,子查询存在,MySQL没有进一步做子查询的优化工作。
示例三,MySQL支持对IN类型的子查询的优化,按也有不支持的情况存在:
IN非相关子查询,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1IN(SELECTa2FROMt2WHEREt2.a2>10);
+----+--------------+-------------+------+------+----------------------------------------------------+ |id|select_type|table|type|key|Extra| +----+--------------+-------------+------+------+----------------------------------------------------+ |1|SIMPLE|<subquery2>|ALL|NULL|NULL| |1|SIMPLE|t1|ALL|NULL|Usingwhere;Usingjoinbuffer(BlockNestedLoop)| |2|MATERIALIZED|t2|ALL|NULL|Usingwhere| +----+--------------+-------------+------+------+----------------------------------------------------+ 3rowsinset,1warning(0.00sec)
被查询优化器处理后的语句为:
/*select#1*/select`test`.`t1`.`id1`AS`id1`,`test`.`t1`.`a1`AS`a1`, `test`.`t1`.`b1`AS`b1` from`test`.`t1`semijoin(`test`.`t2`) where((`test`.`t1`.`a1`=`<subquery2>`.`a2`)and(`test`.`t2`.`a2`>10))
从查询执行计划看,表t2被物化后,与表t1执行了半连接(semijoin)。尽管有“subquery2”这样的内容看起来是子查询,但是表t2已经被上拉到表t1层执行了半连接,所以MySQL支持IN子查询优化为半连接操作。
另外一个IN非相关子查询,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1IN(SELECTa2FROMt2WHEREt2.a2=10);
+----+--------------+-------------+------+------+----------------------------------------------------+ |id|select_type|table|type|key|Extra| +----+--------------+-------------+------+------+----------------------------------------------------+ |1|SIMPLE|<subquery2>|ALL|NULL|Usingwhere| |1|SIMPLE|t1|ALL|NULL|Usingwhere;Usingjoinbuffer(BlockNestedLoop)| |2|MATERIALIZED|t2|ALL|NULL|Usingwhere| +----+--------------+-------------+------+------+----------------------------------------------------+ 3rowsinset,1warning(0.02sec)
被查询优化器处理后的语句为:
/*select#1*/select`test`.`t1`.`id1`AS`id1`,`test`.`t1`.`a1`AS`a1`, `test`.`t1`.`b1`AS`b1` from`test`.`t1`semijoin(`test`.`t2`) where((`<subquery2>`.`a2`=10)and(`test`.`t1`.`a1`=10)and(`test`.`t2`.`a2`=10))
从查询执行计划看,子查询不存在,表t1和t2直接做了块嵌套循环半连接(BlockNestedLoop),把子查询上拉到父查询中用嵌套循环半连接完成IN操作。另外,由于子查询上拉,使得增加连接条件“a1=a2”,而原先的条件“a2=10”可以利用常量传递优化技术,使得“a1=a2=10”,所以查询执行计划中,两个索引扫描的条件分别为:a1=10、a2=10。
另外一个IN非相关子查询,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1IN(SELECTa2FROMt2WHEREt1.a1=10);
+----+-------------+-------+------+------------------------------------------------------------------+ |id|select_type|table|type|Extra| +----+-------------+-------+------+------------------------------------------------------------------+ |1|SIMPLE|t2|ALL|Usingwhere;Starttemporary| |1|SIMPLE|t1|ALL|Usingwhere;Endtemporary;Usingjoinbuffer(BlockNestedLoop)| +----+-------------+-------+------+------------------------------------------------------------------+ 2rowsinset,2warnings(0.00sec)
被查询优化器处理后的语句为:
/*select#1*/select`test`.`t1`.`id1`AS`id1`,`test`.`t1`.`a1`AS`a1`, `test`.`t1`.`b1`AS`b1` from`test`.`t1`semijoin(`test`.`t2`) where((`test`.`t2`.`a2`=10)and(`test`.`t1`.`a1`=10))
从查询执行计划看,子子查询不存在,表t1和t2直接做了块嵌套循环连接(BlockNestedLoop),但属于半连接操作(semijoin),把子查询上拉到父查询中用嵌套循环半连接完成IN操作。
示例四,MySQL支持对NOTIN类型的子查询的优化
NOTIN非相关子查询,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1NOTIN(SELECTa2FROMt2WHEREt2.a2>10);
+----+-------------+-------+------+------+-------------+ |id|select_type|table|type|key|Extra| +----+-------------+-------+------+------+-------------+ |1|PRIMARY|t1|ALL|NULL|Usingwhere| |2|SUBQUERY|t2|ALL|NULL|Usingwhere| +----+-------------+-------+------+------+-------------+ 2rowsinset,1warning(0.02sec)
被查询优化器处理后的语句为:
/*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) having1 ), <primary_index_lookup>( `test`.`t1`.`a1`in<temporarytable>on<auto_key> where((`test`.`t1`.`a1`=`materialized-subquery`.`a2`)) ) ) )) )
从查询执行计划看,表t2做了子查询(SUBQUERY)。而子查询被物化(materialize)。所以,MySQL对于NOTIN子查询采用了物化的优化方式,但不支持子查询的消除。
另外一个NOTIN非相关子查询,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1NOTIN(SELECTa2FROMt2WHEREt2.a2=10);
+----+-------------+-------+------+------+-------------+ |id|select_type|table|type|key|Extra| +----+-------------+-------+------+------+-------------+ |1|PRIMARY|t1|ALL|NULL|Usingwhere| |2|SUBQUERY|t2|ALL|NULL|Usingwhere| +----+-------------+-------+------+------+-------------+ 2rowsinset,1warning(0.00sec)
被查询优化器处理后的语句为:
/*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) having1 ), <primary_index_lookup>( `test`.`t1`.`a1`in<temporarytable>on<auto_key> where((`test`.`t1`.`a1`=`materialized-subquery`.`a2`)) ) ) )) )
从查询执行计划看,表t2做了子查询(SUBQUERY)。而子查询被物化(materialize)。所以,MySQL对于NOTIN子查询采用了物化的优化方式,但不支持子查询的消除。
示例五,MySQL支持对ALL类型的子查询的优化:
不相关的ALL子查询,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1>ALL(SELECTa2FROMt2WHEREt2.a2>10);
+----+-------------+-------+------+------+-------------+ |id|select_type|table|type|key|Extra| +----+-------------+-------+------+------+-------------+ |1|PRIMARY|t1|ALL|NULL|Usingwhere| |2|SUBQUERY|t2|ALL|NULL|Usingwhere| +----+-------------+-------+------+------+-------------+ 2rowsinset,1warning(0.00sec)
被查询优化器处理后的语句为:
/*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>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1=ALL(SELECTa2FROMt2WHEREt2.a2=10);
+----+--------------------+-------+------+------+-------------+ |id|select_type|table|type|key|Extra| +----+--------------------+-------+------+------+-------------+ |1|PRIMARY|t1|ALL|NULL|Usingwhere| |2|DEPENDENTSUBQUERY|t2|ALL|NULL|Usingwhere| +----+--------------------+-------+------+------+-------------+ 2rowsinset,1warning(0.00sec)
被查询优化器处理后的语句为:
/*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*/select1from`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”式的子查询优化用“EXISTSstrategy”方式优化,所以MySQL支持“=ALL”式的子查询优化。
不相关的ALL子查询,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1<ALL(SELECTa2FROMt2WHEREt2.a2=10);
+----+-------------+-------+------+------+-------------+ |id|select_type|table|type|key|Extra| +----+-------------+-------+------+------+-------------+ |1|PRIMARY|t1|ALL|NULL|Usingwhere| |2|SUBQUERY|t2|ALL|NULL|Usingwhere| +----+-------------+-------+------+------+-------------+ 2rowsinset,1warning(0.00sec)
被查询优化器处理后的语句为:
/*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>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1>SOME(SELECTa2FROMt2WHEREt2.a2>10);
+----+-------------+-------+------+------+-------------+ |id|select_type|table|type|key|Extra| +----+-------------+-------+------+------+-------------+ |1|PRIMARY|t1|ALL|NULL|Usingwhere| |2|SUBQUERY|t2|ALL|NULL|Usingwhere| +----+-------------+-------+------+------+-------------+ 2rowsinset,1warning(0.05sec)
被查询优化器处理后的语句为:
/*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*/ selectmin(`test`.`t2`.`a2`) from`test`.`t2` where(`test`.`t2`.`a2`>10) )))
从查询执行计划看,出现了子查询(SUBQUERY),但是,子查询被“min”函数限制,而子查询中的被查询列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“>SOME”式的子查询优化,子查询只被执行一次即可求得最大值。
使用了“=SOME”式子的子查询被优化,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1=SOME(SELECTa2FROMt2WHEREt2.a2=10);
+----+--------------+-------------+------+------+----------------------------------------------------+ |id|select_type|table|type|key|Extra| +----+--------------+-------------+------+------+----------------------------------------------------+ |1|SIMPLE|<subquery2>|ALL|NULL|Usingwhere| |1|SIMPLE|t1|ALL|NULL|Usingwhere;Usingjoinbuffer(BlockNestedLoop)| |2|MATERIALIZED|t2|ALL|NULL|Usingwhere| +----+--------------+-------------+------+------+----------------------------------------------------+ 3rowsinset,1warning(0.01sec)
被查询优化器处理后的语句为:
/*select#1*/select`test`.`t1`.`id1`AS`id1`,`test`.`t1`.`a1`AS`a1`, `test`.`t1`.`b1`AS`b1` from`test`.`t1`semijoin(`test`.`t2`) where((`<subquery2>`.`a2`=10)and(`test`.`t1`.`a1`=10)and(`test`.`t2`.`a2`=10))
从查询执行计划看,没有出现了子查询,表t2被物化,与表t1进行了半连接。
使用了“<SOME”式子的子查询被优化,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1<SOME(SELECTa2FROMt2WHEREt2.a2=10);
+----+-------------+-------+------+------+-------------+ |id|select_type|table|type|key|Extra| +----+-------------+-------+------+------+-------------+ |1|PRIMARY|t1|ALL|NULL|Usingwhere| |2|SUBQUERY|t2|ALL|NULL|Usingwhere| +----+-------------+-------+------+------+-------------+ 2rowsinset,1warning(0.00sec)
被查询优化器处理后的语句为:
/*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*/ selectmax(`test`.`t2`.`a2`) from`test`.`t2` where(`test`.`t2`.`a2`=10) ) ) )
从查询执行计划看,出现了子查询(SUBQUERY),但是,子查询被“max”函数限制,而子查询中的被查询列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“<SOME”式的子查询优化,子查询只被执行一次即可求得最大值。
示例七,MySQL支持对ANY类型的子查询的优化:
使用了“>ANY”式子的子查询被优化,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1>ANY(SELECTa2FROMt2WHEREt2.a2>10);
+----+-------------+-------+------+------+-------------+ |id|select_type|table|type|key|Extra| +----+-------------+-------+------+------+-------------+ |1|PRIMARY|t1|ALL|NULL|Usingwhere| |2|SUBQUERY|t2|ALL|NULL|Usingwhere| +----+-------------+-------+------+------+-------------+ 2rowsinset,1warning(0.00sec)
被查询优化器处理后的语句为:
/*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*/ selectmin(`test`.`t2`.`a2`) from`test`.`t2` where(`test`.`t2`.`a2`>10) ) ) )
从查询执行计划看,出现了子查询(SUBQUERY),但是,子查询被“min”函数限制,而子查询中的被查询列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“>ANY”式的子查询优化,子查询只被执行一次即可求得最小值。
使用了“=ANY”式子的子查询被优化,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1=ANY(SELECTa2FROMt2WHEREt2.a2>10);
+----+--------------+-------------+------+------+----------------------------------------------------+ |id|select_type|table|type|key|Extra| +----+--------------+-------------+------+------+----------------------------------------------------+ |1|SIMPLE|<subquery2>|ALL|NULL|NULL| |1|SIMPLE|t1|ALL|NULL|Usingwhere;Usingjoinbuffer(BlockNestedLoop)| |2|MATERIALIZED|t2|ALL|NULL|Usingwhere| +----+--------------+-------------+------+------+----------------------------------------------------+ 3rowsinset,1warning(0.02sec)
被查询优化器处理后的语句为:
/*select#1*/select`test`.`t1`.`id1`AS`id1`,`test`.`t1`.`a1`AS`a1`, `test`.`t1`.`b1`AS`b1` from`test`.`t1`semijoin(`test`.`t2`) where((`test`.`t1`.`a1`=`<subquery2>`.`a2`)and(`test`.`t2`.`a2`>10))
从查询执行计划看,没有出现了子查询,表t2被物化,与表t1进行了半连接。
使用了“<ANY”式子的子查询被优化,查询执行计划如下:
mysql>EXPLAINEXTENDEDSELECT*FROMt1WHEREt1.a1<ANY(SELECTa2FROMt2WHEREt2.a2>10);
+----+-------------+-------+------+------+-------------+ |id|select_type|table|type|key|Extra| +----+-------------+-------+------+------+-------------+ |1|PRIMARY|t1|ALL|NULL|Usingwhere| |2|SUBQUERY|t2|ALL|NULL|Usingwhere| +----+-------------+-------+------+------+-------------+ 2rowsinset,1warning(0.00sec)
被查询优化器处理后的语句为:
/*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*/ selectmax(`test`.`t2`.`a2`) from`test`.`t2` where(`test`.`t2`.`a2`>10) ) ) )
从查询执行计划看,出现了子查询(SUBQUERY),但是,子查询被“max”函数限制,而子查询中的被查询列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“<ANY”式的子查询优化,子查询只被执行一次即可求得最大值。