SQL优化(一) ---- in和exist

1.背景:

基础表:

原始场景不贴了,贴出一个相似场景,有3张表,

学生表(t_student) --> 100000条数据,总共有10万个学生

课程表(t_course) --> 30条数据,总共有30种课程

得分表(t_score) --> 300万数据,每个学生的每一门课程的得分

需求:

查询出语文得分是87分的学生Id。

最早版本的sql:

select s.* from t_student s where s.sid in (select sid from t_score sc where sc.cid = 1 and sc.score = 87);

在以上数据的基础上,我们执行一次,发现已经等不到结果了,一直卡住,像死掉了一般;

1. 分析:

1. explain打开执行计划:

1.1 第一个直观感觉,可以加索引解决问题,因为此时type都是ALL。

1.2 DEPENDENT SUBQUERY这个关键字可不是什么好东西,暂时放着,不去管这个。

2. 先根据第一反应,加索引,没有什么是不能通过索引解决的。

CREATE index sc_c_id_index on t_score(cid);
CREATE index sc_c_score_index on t_score(score);

2.1 执行查询语句:

发现依然没法短时间查询出结果,本机等了10分钟没结果,果断砸了~~~~~

2.2 改变加索引的方式,做成覆盖索引:

2.2 执行语句: 终于出结果了,主要是利用覆盖索引的特性,直接在索引里查到sid,不需要二次查询,节省了时间

2.3 查看执行计划,总的来说不错,解决了问题。

2. 优化部分:

但是,我们一开始就使用了索引去优化,其实本身并没有对sql去分析一下,也就是没使用最优的sql,这点问题被索引的高效掩盖了,是一个隐藏的问题。

2.1 分析

我们发现,其实in查询这边可以改成连接查询,其实可以通过表的关联来查询,不必使用in查询这种容易炸的sql语法。

2.1 擦,不使用索引的基础上竟然只要1.1秒就查出数据了,可见in 中带子查询是多么坑的一件事,慎用~~~~

2.2 看下优化后的sql语句吧。

select `test`.`s`.`sid` AS `sid`,`test`.`s`.`name` AS `name` 
from `test`.`t_student` `s` join `test`.`t_score` `sc` 
where ((`test`.`s`.`sid` = `test`.`sc`.`sid`) and (`test`.`sc`.`cid` = 1) and (`test`.`sc`.`score` = '87'))

2.3 我们知道,sql语句的执行顺序是下面的顺序,因此这个sql是先去进行join,然后再进行where条件的过滤。

select[distinct]  
from  
join(如left join)  
on  
where  
group by  
having  
union  
order by  
limit  

2.4 再次优化,能不能我们先过滤出where里的特定条件,然后再join,这样又能再次排除一些垃圾数据了

擦泪,,结果并没有好,反而比先join后where的情况更差了点。

可以看见唯一的区别就是本来以为可以提高效率的查询多出一个DERIVED过程

最后。我们选择优化之后的第一个版本,先join后where吧,然后我们再跟进需求加上特定索引。注意索引最左匹配原则。

CREATE index sc_sid_index on t_score(sid);
CREATE index sc_cid_index on t_score(cid,score);

走一波:

起飞~~~~~~~~~~~~~~

最后回到主题上来,in和exist还是慎用比较好,当然不是绝对。

另外就是  A in B 时,最好B表数据少为优。 A exist B 时, A表数据少为优。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值