聊聊sql优化的15个小技巧,太赞了

前言sql优化是一个大家都比较关注的热门话题,无论你在面试,还是工作中,都很有可能会遇到 。
如果某天你负责的某个线上接口,出现了性能问题,需要做优化 。那么你首先想到的很有可能是优化sql语句,因为它的改造成本相对于代码来说也要小得多 。
那么,如何优化sql语句呢?
这篇文章从15个方面,分享了sql优化的一些小技巧,希望对你有所帮助 。

聊聊sql优化的15个小技巧,太赞了

文章插图
 
1 避免使用select *很多时候,我们写sql语句时,为了方便,喜欢直接使用select *,一次性查出表中所有列的数据 。
反例:
select * from user where id=1;在实际业务场景中,可能我们真正需要使用的只有其中一两列 。查了很多数据,但是不用,白白浪费了数据库资源,比如:内存或者cpu 。
此外,多查出来的数据,通过网络IO传输的过程中,也会增加数据传输的时间 。
还有一个最重要的问题是:select *不会走覆盖索引,会出现大量的回表操作,而从导致查询sql的性能很低 。
那么,如何优化呢?
正例:
【聊聊sql优化的15个小技巧,太赞了】select name,age from user where id=1;sql语句查询时,只查需要用到的列,多余的列根本无需查出来 。
2 用union all代替union我们都知道sql语句使用union关键字后,可以获取排重后的数据 。
而如果使用union all关键字,可以获取所有数据,包含重复的数据 。
反例:
(select * from user where id=1) union (select * from user where id=2);排重的过程需要遍历、排序和比较,它更耗时,更消耗cpu资源 。
所以如果能用union all的时候,尽量不用union 。
正例:
(select * from user where id=1) union all(select * from user where id=2);除非是有些特殊的场景,比如union all之后,结果集中出现了重复数据,而业务场景中是不允许产生重复数据的,这时可以使用union 。
3 小表驱动大表小表驱动大表,也就是说用小表的数据集驱动大表的数据集 。
假如有order和user两张表,其中order表有10000条数据,而user表有100条数据 。
这时如果想查一下,所有有效的用户下过的订单列表 。
可以使用in关键字实现:
select * from orderwhere user_id in (select id from user where status=1)也可以使用exists关键字实现:
select * from orderwhere exists (select 1 from user where order.user_id = user.id and status=1)前面提到的这种业务场景,使用in关键字去实现业务需求,更加合适 。
为什么呢?
因为如果sql语句中包含了in关键字,则它会优先执行in里面的子查询语句,然后再执行in外面的语句 。如果in里面的数据量很少,作为条件查询速度更快 。
而如果sql语句中包含了exists关键字,它优先执行exists左边的语句(即主查询语句) 。然后把它作为条件,去跟右边的语句匹配 。如果匹配上,则可以查询出数据 。如果匹配不上,数据就被过滤掉了 。
这个需求中,order表有10000条数据,而user表有100条数据 。order表是大表,user表是小表 。如果order表在左边,则用in关键字性能更好 。
总结一下:
  • in 适用于左边大表,右边小表 。
  • exists 适用于左边小表,右边大表 。
不管是用in,还是exists关键字,其核心思想都是用小表驱动大表 。
4 批量操作如果你有一批数据经过业务处理之后,需要插入数据,该怎么办?
反例:
for(Order order: list){orderMApper.insert(order):}在循环中逐条插入数据 。
insert into order(id,code,user_id) values(123,'001',100);该操作需要多次请求数据库,才能完成这批数据的插入 。
但众所周知,我们在代码中,每次远程请求数据库,是会消耗一定性能的 。而如果我们的代码需要请求多次数据库,才能完成本次业务功能,势必会消耗更多的性能 。
那么如何优化呢?
正例:
orderMapper.insertBatch(list):提供一个批量插入数据的方法 。
insert into order(id,code,user_id) values(123,'001',100),(124,'002',100),(125,'003',101);这样只需要远程请求一次数据库,sql性能会得到提升,数据量越多,提升越大 。
但需要注意的是,不建议一次批量操作太多的数据,如果数据太多数据库响应也会很慢 。批量操作需要把握一个度,建议每批数据尽量控制在500以内 。如果数据多于500,则分多批次处理 。


推荐阅读