MySQL:子查询优化


风晓
风晓 2023-12-28 13:59:03 51647 赞同 0 反对 0
分类: 资源
本文主要讲子查询优化

查询演员Penelope Guiness(actor_id = 1)参演过的所有电影,查询会是这么写

select * from sakila.film where film_id in(select film_id from sakila.film_actor where actor_id =1);

因为 MySQL 对 In()列表中的选项有专门的优化策略,一般会认为 MySQL 会先执行子查询返回所有包含 actor_id 为 1 的 film_id。一般来说 in ()列表查询速度很快,所以会认为上面的查询会这样执行

select GROUP_CONCAT(film_id)from sakila.film_actor where actor_id = 1;

result : 1,23,25,106,140,166,277等等

select * from sakila.film where film_id IN ( result的结果集 )。

很不幸的是,MySQL 不是这样做的。MySQL 会将相关的外层表压到子查询中,认为这样可以更高效率的查找数据行。即 MySQL 会将查询改写成下面的样子:

EXISTS函数的用法参考,关于exists和In,当外表>子查询表 的时候可以用in,当外表<子查询表的时候,可以用exists。exists先全表扫描外层的表。

这时候子查询就需要根据 film_id来关联外层的 film 表了,里面子查询是 film_actor 表 和 film 表。而关联的条件是 film_id 。 因为需要 film_id 这个字段,所以 MySQL 认为无法先执行这个子查询。通过explain执行计划可以看到这个子查询是一个相关子查询:

根据这个执行计划可以知道,先执行的是 film 表,film表在外层,所以 MySQL 先对外层的film表进行全表扫描ALL,然后根据返回的 film_id 再逐个执行子查询,如果外面这个film表是一个很大的表的话,那么性能是很糟糕的。当然我们可以重写子查询为:


到这里一定认为 子查询 exist / not exist 比连表 join 慢?其实错了,不同的场景,不同的sql下,不一定子查询效率低。有可能子查询的QPS高。

如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!

评价 0 条
风晓L1
粉丝 1 资源 2038 + 关注 私信
最近热门资源
银河麒麟桌面操作系统备份用户数据  125
统信桌面专业版【全盘安装UOS系统】介绍  120
银河麒麟桌面操作系统安装佳能打印机驱动方法  112
银河麒麟桌面操作系统 V10-SP1用户密码修改  105
最近下载排行榜
银河麒麟桌面操作系统备份用户数据 0
统信桌面专业版【全盘安装UOS系统】介绍 0
银河麒麟桌面操作系统安装佳能打印机驱动方法 0
银河麒麟桌面操作系统 V10-SP1用户密码修改 0
作者收入月榜
1

prtyaa 收益393.62元

2

zlj141319 收益218元

3

1843880570 收益214.2元

4

IT-feng 收益209.03元

5

风晓 收益208.24元

6

777 收益172.71元

7

Fhawking 收益106.6元

8

信创来了 收益105.84元

9

克里斯蒂亚诺诺 收益91.08元

10

技术-小陈 收益79.5元

请使用微信扫码

加入交流群

请使用微信扫一扫!