Mysql学习MySQL的子查询及相关优化学习教程

《Mysql学习MySQL的子查询及相关优化学习教程》要点:
本文介绍了Mysql学习MySQL的子查询及相关优化学习教程,希望对您有用。如果有疑问,可以联系我们。

一、子查询
1、where型子查询
(把内层查询结果当作外层查询的比较条件)
MYSQL学习

#不用order by 来查询最新的商品
select goods_id,goods_name from goods where goods_id = (select max(goods_id) from goods);
#取出每个栏目下最新的产品(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型子查询
(把内层的查询结果供外层再次查询)
#用子查询查出挂科两门及以上的同学的平均成绩
思路:
MYSQL学习

#先查出哪些同学挂科两门以上
select name,count(*) as gk from stu where score < 60 having gk >=2;
#以上查询结果,我们只要名字就可以了,所以再取一次名字
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型子查询
(把外层查询结果拿到内层,看内层的查询是否成立)
MYSQL学习

#查询哪些栏目下有商品,栏目表category,商品表goods
select cat_id,cat_name from category where exists(select * from goods where goods.cat_id = category.cat_id);

二、优化
从句式的形式看,子查询分为特殊格式子查询和非特殊格式子查询,特殊格式的子查询中又包括IN、ALL、ANY、SOME、EXISTS等类型的子查询,对于有的类型的子查询,MySQL有的支持优化,有的不支持,具体情况如下.MYSQL学习

MYSQL学习

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

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

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)

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

/* 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))
)

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

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

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)

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

/* select#1 */ select `test`.`t1`.`id1` AS `id1`,`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))
)

从查询执行计划看,MySQL没有进一步做子查询的优化工作.MYSQL学习

MYSQL学习

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

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

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,`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没有进一步做子查询的优化工作.MYSQL学习

MYSQL学习

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

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)

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

/* select#1 */ select `test`.`t1`.`id1` AS `id1`,`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学习

MYSQL学习

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

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

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)

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

/* select#1 */ select `test`.`t1`.`id1` AS `id1`,`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子查询优化为半连接操作.MYSQL学习

MYSQL学习

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

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)

dawei

【声明】:淮南站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。