mysql in 查询原理_Mysql笔记~ In型子查询陷阱

这世界大千,

渺渺云烟

总有,你想不到的天

故事里,重复的对白

如今都飞向天外

镜中繁星眨着眼

像是,天边飞过的杜鹃

------ 题记 · 胡思乱想 · 啥也不说先赋诗一首

现在有两个表,ta和tb,ta有1千万条数据(id 主键索引),tb有三条数据(uid字段 3,5,7);

select * from ta where id in ( select uid from tb );

定睛一看,感觉这条语句应该很快。

可能你会一厢情愿的以为先执行括号里面的语句,然后在执行外层的select。外层的select用上了id主键速度应该飞起来才对。

不好意思。实际上这条语句执行非常慢。

通过explain分析,这条语句没有用上索引,而是全表扫描。WHY?

实际上MySQL内部不是照着我们的想法来运行的,你以为你以为的,就是你以为的?

它是从外层执行开始,每扫一行就把id拿来和内层查询比较,所以这里是可怕的全表扫描。

修正语句:

select * from ta where id in ( 3,5,7 ); (在MySQL内部in会被自动转化为exists)

执行时间变成了毫秒级,通过explain查看使用了range扫描,可以看出MySQL内部操作原理。

然后我们再来看一下有没有解决方案:

select ta.* from ta inner join tb on ta.id=tb.uid;

查询时间也是毫秒级。

这次通过 explain发现 ,MySQL先执行了select uid from tb,然后执行select ta并且使用了eq_ref一对一索引。

子查询陷阱

select id,name from lx_com where id in (select id from ids);//INT查询陷阱,问题很严重,并非想象中的先执行子查询

已知lx_com是一张很大的表,而子查询的ids表示一张很小表。

那为什么会导致查询非常非常非常之慢呢?

是因为MySQL并不是先执行子查询,而是从lx_com表中取出一行,然后再执行子查询,比较是否在子查询中,

这样一来,就等于执行了lx_com总量数据*ids总量数据的好几倍的全表扫描

改进方案:

select lx_com.id,name from lx_com inner join ids on lx_com.id = Domain Premium: ids.id;

通过EXPLAIN发现,这次对ids表进行了全表扫描,不过这没关系,因为ids表非常小。而lx_com的type显示的是eq_ref精确查询。

所以速度非常快。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值