前言
mysql是项目中常用的数据库,其中in查询也是很常用。最近项目调试过程中,遇到一个出乎意料的select查询,竟然用了33秒!
一、表结构1. userinfo 表
2. article 表
select*fromuserinfowhereidin(selectauthor_idfromartilcewheretype=1);登录后复制
大家第一眼看到上面的SQL时,可能都会觉得这是一个很简单的子查询。先把author_id查出来,再用in查询一下。
如果有相关索引会非常快的,拆解来讲就是以下这样的:
1.selectauthor_idfromartilcewheretype=1; 2.select*fromuserinfowhereidin(1,2,3);登录后复制
但是事实是这样的:
mysql> select count(*) from userinfo;登录后复制
mysql> select count(*) from article;登录后复制
mysql> select id,username from userinfo where id in (select author_id from article where type = 1);登录后复制
33 秒!为什么会这么慢呢?
三、问题原因官方文档解释:in 子句在查询的时候有时会被转换为 exists 的方式来执行,变成逐条记录进行遍历(版本 5.5 中存在,5.6 中已做优化)。
参考:
https://dev.mysql.com/doc/refman/5.5/en/subquery-optimization.html
四、解决方式(版本5.5)1. 使用临时表
select id,username from userinfo where id in (select author_id from (select author_id from article where type = 1) as tb);登录后复制
2. 使用 join
select a.id,a.username from userinfo a, article b where a.id = b.author_id and b.type = 1;登录后复制 五、补充
版本 5.6 已针对子查询做了优化,方式跟【四】中的临时表方式一样,参考官方文档:
If materialization is not used, the optimizer sometimes rewrites a noncorrelated subquery as a correlated subquery.
For example, the following IN subquery is noncorrelated ( where_condition involves only columns from t2 and not t1 ):
select * from t1
where t1.a in (select t2.b from t2 where where_condition);
The optimizer might rewrite this as an EXISTS correlated subquery:
select * from t1
where exists (select t2.b from t2 where where_condition and t1.a=t2.b);
Subquery materialization using a temporary table avoids such rewrites and makes it possible to execute the subquery only once rather than once per row of the outer query.
https://dev.mysql.com/doc/refman/5.6/en/subquery-materialization.html
文章来自微信公众号:HULK一线技术杂谈
以上就是记踩到 MySQL in 子查询的“坑”的详细内容,更多请关注慧达安全导航其它相关文章!
免责 声明
1、本网站名称:慧达安全导航
2、本站永久网址:https//www.huida178.com/
3、本站所有资源来源于网友投稿和高价购买,所有资源仅对编程人员及源代码爱好者开放下载做参考和研究及学习,本站不提供任何技术服务!
4、本站所有资源的属示图片和信息不代表本站的立场!本站只是储蓄平台及搬运
5、下载者禁止在服务器和虚拟机下进行搭建运营,本站所有资源不支持联网运行!只允许调试,参考和研究!!!!
6、未经原版权作者许可禁止用于任何商业环境,任何人不得擅作它用,下载者不得用于违反国家法律,否则发生的一切法律后果自行承担!
7、为尊重作者版权,请在下载24小时内删除!请购买原版授权作品,支持你喜欢的作者,谢谢!
8.若资源侵犯了您的合法权益,请持 您的版权证书和相关原作品信息来信通知我们!QQ:1247526623我们会及时删除,给您带来的不便,我们深表歉意!
9、如下载链接失效、广告或者压缩包问题请联系站长处理
10、如果你也有好源码或者教程,可以发布到网站,分享有金币奖励和额外收入!
11、本站资源售价只是赞助,收取费用仅维持本站的日常运营所需
12、因源码具有可复制性,一经赞助,不得以任何形式退款。
13、本文内容由网友自发贡献和站长收集,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系1247526623@qq.com
转载请注明出处: 慧达安全导航 » 记踩到 MySQL in 子查询的“坑”
发表评论 取消回复