MySQL的子查詢及相關(guān)優(yōu)化學習教程
一、子查詢
1、where型子查詢
(把內(nèi)層查詢結(jié)果當作外層查詢的比較條件)
#不用order by 來查詢最新的商品 select goods_id,goods_name from goods where goods_id = (select max(goods_id) from goods);
#取出每個欄目下最新的產(chǎn)品(goods_id唯一) select cat_id,goods_id,goods_name from goods where goods_id in(select max(goods_id) from goods group by cat_id);
2、from型子查詢
(把內(nèi)層的查詢結(jié)果供外層再次查詢)
#用子查詢查出掛科兩門及以上的同學的平均成績
思路:
#先查出哪些同學掛科兩門以上 select name,count(*) as gk from stu where score < 60 having gk >=2; #以上查詢結(jié)果,我們只要名字就可以了,所以再取一次名字 select name from (select name,count(*) as gk from stu having gk >=2) as t; #找出這些同學了,那么再計算他們的平均分 select name,avg(score) from stu where name in (select name from (select name,count(*) as gk from stu having gk >=2) as t) group by name;
3、exists型子查詢
(把外層查詢結(jié)果拿到內(nèi)層,看內(nèi)層的查詢是否成立)
#查詢哪些欄目下有商品,欄目表category,商品表goods select cat_id,cat_name from category where exists(select * from goods where goods.cat_id = category.cat_id);
二、優(yōu)化
從句式的形式看,子查詢分為特殊格式子查詢和非特殊格式子查詢,特殊格式的子查詢中又包括IN、ALL、ANY、SOME、EXISTS等類型的子查詢,對于有的類型的子查詢,MySQL有的支持優(yōu)化,有的不支持,具體情況如下。
示例一,MySQL不支持對EXISTS類型的子查詢的優(yōu)化:
EXISTS類型的相關(guān)子查詢,查詢執(zhí)行計劃如下:
mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE 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)
被查詢優(yōu)化器處理后的語句為:
/* select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`, `test`.`t1`.`b1` AS `b1` from `test`.`t1` where exists(/* select#2 */ select 1 from `test`.`t2` where ((`test`.`t1`.`a1` = `test`.`t2`.`a2`) and (`test`.`t2`.`a2` > 10)) )
從查詢執(zhí)行計劃看,子查詢存在,MySQL沒有進一步做子查詢的優(yōu)化工作。
另外的一個EXISTS類型的相關(guān)子查詢,查詢執(zhí)行計劃如下:
mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t1.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)
被查詢優(yōu)化器處理后的語句為:
/* select#1 */ select `test`.`t1`.`id1` AS `id1`,`test`.`t1`.`a1` AS `a1`, `test`.`t1`.`b1` AS `b1` from `test`.`t1` where exists(/* select#2 */ select 1 from `test`.`t2` where ((`test`.`t1`.`b1` = `test`.`t2`.`b2`) and (`test`.`t1`.`a1` = 10)) )
從查詢執(zhí)行計劃看,子查詢存在,MySQL沒有進一步做子查詢的優(yōu)化工作。
示例二,MySQL不支持對NOT EXISTS類型的子查詢的優(yōu)化:
NOT EXISTS類型的相關(guān)子查詢,查詢執(zhí)行計劃如下:
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)
被查詢優(yōu)化器處理后的語句為:
/* 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)))) )
從查詢執(zhí)行計劃看,子查詢存在,MySQL沒有進一步做子查詢的優(yōu)化工作。
另外的一個NOT EXISTS類型的相關(guān)子查詢,查詢執(zhí)行計劃如下:
mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE NOT EXISTS (SELECT 1 FROM t2 WHERE t1.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)
被查詢優(yōu)化器處理后的語句為:
/* 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)))) )
從查詢執(zhí)行計劃看,子查詢存在,MySQL沒有進一步做子查詢的優(yōu)化工作。
示例三,MySQL支持對IN類型的子查詢的優(yōu)化,按也有不支持的情況存在:
IN非相關(guān)子查詢,查詢執(zhí)行計劃如下:
mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 IN (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.00 sec)
被查詢優(yōu)化器處理后的語句為:
/* 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))
從查詢執(zhí)行計劃看,表t2被物化后,與表t1執(zhí)行了半連接(semi join)。盡管有“subquery2”這樣的內(nèi)容看起來是子查詢,但是表t2已經(jīng)被上拉到表t1層執(zhí)行了半連接,所以MySQL支持IN子查詢優(yōu)化為半連接操作。
另外一個IN非相關(guān)子查詢,查詢執(zhí)行計劃如下:
mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 IN (SELECT a2 FROM t2 WHERE t2.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.02 sec)
被查詢優(yōu)化器處理后的語句為:
/* 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))
從查詢執(zhí)行計劃看,子查詢不存在,表t1和t2直接做了塊嵌套循環(huán)半連接(Block Nested Loop),把子查詢上拉到父查詢中用嵌套循環(huán)半連接完成IN操作。另外,由于子查詢上拉,使得增加連接條件“a1=a2”,而原先的條件“a2=10”可以利用常量傳遞優(yōu)化技術(shù),使得“a1=a2=10”,所以查詢執(zhí)行計劃中,兩個索引掃描的條件分別為:a1 = 10、a2 = 10。
另外一個IN非相關(guān)子查詢,查詢執(zhí)行計劃如下:
mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a1 IN (SELECT a2 FROM t2 WHERE t1.a1=10);
+----+-------------+-------+------+------------------------------------------------------------------+ | id | select_type | table | type | Extra | +----+-------------+-------+------+------------------------------------------------------------------+ | 1 | SIMPLE | t2 | ALL | Using where; Start temporary | | 1 | SIMPLE | t1 | ALL | Using where; End temporary; Using join buffer (Block Nested Loop)| +----+-------------+-------+------+------------------------------------------------------------------+ 2 rows in set, 2 warnings (0.00 sec)
被查詢優(yōu)化器處理后的語句為:
/* 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))
從查詢執(zhí)行計劃看,子子查詢不存在,表t1和t2直接做了塊嵌套循環(huán)連接(Block Nested Loop),但屬于半連接操作(semi join),把子查詢上拉到父查詢中用嵌套循環(huán)半連接完成IN操作。
示例四,MySQL支持對NOT IN類型的子查詢的優(yōu)化
NOT IN非相關(guān)子查詢,查詢執(zhí)行計劃如下:
mysql> EXPLAIN EXTENDED SELECT * 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.02 sec)
被查詢優(yōu)化器處理后的語句為:
/* 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 <temporary table> on <auto_key> where ((`test`.`t1`.`a1` = `materialized-subquery`.`a2`)) ) ) )) )
從查詢執(zhí)行計劃看,表t2做了子查詢(SUBQUERY)。而子查詢被物化(materialize)。所以,MySQL對于NOT IN子查詢采用了物化的優(yōu)化方式,但不支持子查詢的消除。
另外一個NOT IN非相關(guān)子查詢,查詢執(zhí)行計劃如下:
mysql> EXPLAIN EXTENDED SELECT * 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)
被查詢優(yōu)化器處理后的語句為:
/* 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 <temporary table> on <auto_key> where ((`test`.`t1`.`a1` = `materialized-subquery`.`a2`)) ) ) )) )
從查詢執(zhí)行計劃看,表t2做了子查詢(SUBQUERY)。而子查詢被物化(materialize)。所以,MySQL對于NOT IN子查詢采用了物化的優(yōu)化方式,但不支持子查詢的消除。
示例五,MySQL支持對ALL類型的子查詢的優(yōu)化:
不相關(guān)的ALL子查詢,查詢執(zhí)行計劃如下:
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 rows in set, 1 warning (0.00 sec)
被查詢優(yōu)化器處理后的語句為:
/* 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) ) ))
從查詢執(zhí)行計劃看,出現(xiàn)了子查詢(SUBQUERY),但是,子查詢被“<= <max>”操作符限制,而子查詢中的被查詢列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“>ALL”式的子查詢優(yōu)化,子查詢只被執(zhí)行一次即可求得最大值。
不相關(guān)的ALL子查詢,查詢執(zhí)行計劃如下:
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 | DEPENDENT SUBQUERY | t2 | ALL | NULL | Using where | +----+--------------------+-------+------+------+-------------+ 2 rows in set, 1 warning (0.00 sec)
被查詢優(yōu)化器處理后的語句為:
/* 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) ) ))
從查詢執(zhí)行計劃看,出現(xiàn)了子查詢(SUBQUERY),但是被查詢優(yōu)化器處理后的語句中包含“exists”,這表明MySQL對于“=ALL”式的子查詢優(yōu)化用“EXISTS strategy”方式優(yōu)化,所以MySQL支持“=ALL”式的子查詢優(yōu)化。
不相關(guān)的ALL子查詢,查詢執(zhí)行計劃如下:
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 rows in set, 1 warning (0.00 sec)
被查詢優(yōu)化器處理后的語句為:
/* 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) ) ))
從查詢執(zhí)行計劃看,出現(xiàn)了子查詢(SUBQUERY),但是,子查詢被“>= <min>”操作符限制,而子查詢中的被查詢列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“<ALL”式的子查詢優(yōu)化,子查詢只被執(zhí)行一次即可求得最小值。
示例六,MySQL支持對SOME類型的子查詢的優(yōu)化:
使用了“>SOME”式子的子查詢被優(yōu)化,查詢執(zhí)行計劃如下:
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 rows in set, 1 warning (0.05 sec)
被查詢優(yōu)化器處理后的語句為:
/* 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) )))
從查詢執(zhí)行計劃看,出現(xiàn)了子查詢(SUBQUERY),但是,子查詢被“min”函數(shù)限制,而子查詢中的被查詢列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“>SOME”式的子查詢優(yōu)化,子查詢只被執(zhí)行一次即可求得最大值。
使用了“=SOME”式子的子查詢被優(yōu)化,查詢執(zhí)行計劃如下:
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 | 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)
被查詢優(yōu)化器處理后的語句為:
/* 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))
從查詢執(zhí)行計劃看,沒有出現(xiàn)了子查詢,表t2被物化,與表t1進行了半連接。
使用了“<SOME”式子的子查詢被優(yōu)化,查詢執(zhí)行計劃如下:
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 rows in set, 1 warning (0.00 sec)
被查詢優(yōu)化器處理后的語句為:
/* 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) ) ) )
從查詢執(zhí)行計劃看,出現(xiàn)了子查詢(SUBQUERY),但是,子查詢被“max”函數(shù)限制,而子查詢中的被查詢列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“<SOME”式的子查詢優(yōu)化,子查詢只被執(zhí)行一次即可求得最大值。
示例七,MySQL支持對ANY類型的子查詢的優(yōu)化:
使用了“>ANY”式子的子查詢被優(yōu)化,查詢執(zhí)行計劃如下:
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 | PRIMARY | t1 | ALL | NULL | Using where | | 2 | SUBQUERY | t2 | ALL | NULL | Using where | +----+-------------+-------+------+------+-------------+ 2 rows in set, 1 warning (0.00 sec)
被查詢優(yōu)化器處理后的語句為:
/* 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) ) ) )
從查詢執(zhí)行計劃看,出現(xiàn)了子查詢(SUBQUERY),但是,子查詢被“min”函數(shù)限制,而子查詢中的被查詢列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“>ANY”式的子查詢優(yōu)化,子查詢只被執(zhí)行一次即可求得最小值。
使用了“=ANY”式子的子查詢被優(yōu)化,查詢執(zhí)行計劃如下:
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)
被查詢優(yōu)化器處理后的語句為:
/* 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))
從查詢執(zhí)行計劃看,沒有出現(xiàn)了子查詢,表t2被物化,與表t1進行了半連接。
使用了“<ANY”式子的子查詢被優(yōu)化,查詢執(zhí)行計劃如下:
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 | PRIMARY | t1 | ALL | NULL | Using where | | 2 | SUBQUERY | t2 | ALL | NULL | Using where | +----+-------------+-------+------+------+-------------+ 2 rows in set, 1 warning (0.00 sec)
被查詢優(yōu)化器處理后的語句為:
/* 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) ) ) )
從查詢執(zhí)行計劃看,出現(xiàn)了子查詢(SUBQUERY),但是,子查詢被“max”函數(shù)限制,而子查詢中的被查詢列a2上存在唯一索引,所以可以利用索引求最值,所以MySQL支持“<ANY”式的子查詢優(yōu)化,子查詢只被執(zhí)行一次即可求得最大值。
相關(guān)文章
IDEA配置連接MYSQL數(shù)據(jù)庫遇到Failed這個問題解決
這篇文章主要介紹了IDEA配置連接MYSQL數(shù)據(jù)庫遇到Failed這個問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-11-11MySQL使用select語句查詢指定表中指定列(字段)的數(shù)據(jù)
本文介紹MySQL數(shù)據(jù)庫中執(zhí)行select查詢語句,查詢指定列的數(shù)據(jù),即指定字段的數(shù)據(jù),需要的朋友可以參考下2016-11-11MySQL 數(shù)據(jù)庫設(shè)計復習筆記及項目實戰(zhàn)
參考的數(shù)據(jù)庫文檔主要有:目前國內(nèi)的常見的PHP系統(tǒng)的數(shù)據(jù)庫2010-03-03MySQL數(shù)據(jù)庫中把int轉(zhuǎn)化varchar引發(fā)的慢查詢
這篇文章主要介紹了MySQL數(shù)據(jù)庫中把int轉(zhuǎn)化varchar引發(fā)的慢查詢 的相關(guān)資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下2016-07-07