随笔背景:虽然参与正式项目开发已经近两年了,但是之前涉及的数据都不是很大,就算数据量够了,但是也没涉及到统计,所以之前开发的时候仅仅注意业务逻辑是否正确,代码是否精简。本次做的一个项目,写数据统计的接口,刚开始也只是注意逻辑,不过后来数据量仅仅到了40万的时候,一个按照年龄区段获取各年龄的普及率接口竟然花了近一分钟,所以开始了我的优化路程。
一、从SQL上来看,首先想到的是把SQL上的业务逻辑拿出来,放到代码里面实现。比如这里根据年龄区段获取各年龄的普及率,可以把拆成两个SQL,一个统计各年龄段总人数,一个统计各年龄段普及的人数,具体计算比例可以在代码实现。原理是SQL里面加上逻辑处理的话是针对大数量的逻辑处理,而代码处理的话仅仅是对已经统计过的数据处理,这样对比一下逻辑处理的对象就知道为啥快点了。
如: select sum(case when a.answer != '01' then 1 else 0 end)/count(a.id) pjl from tableA a group by a.age
拆分: select count(a.id) from tableA a where a. answer != '01' group by a.age
select count(a.id) from tableA a where group by a.age
二、不是说所有的子查询都会比较慢,都是不好的。个人之前觉得子查询很耗性能,明明可以关联查询的,为什么还要子查询。然后本次发现其实合理的利用子查询可以有效的提高速率,如可以通过子查询筛选一部分数据,然后再对筛选后的数据关联。
如:select a.name,a.code from tableA a left join tableB b on b.code = a.code where b.status = '2'
修改:select a.name,a.code from tableA a where a.code in (select code from tableB where status = '2')
原SQL是先关联然后筛选数据的,关联笛卡尔积 乘法的概念,可以理解为先把所有数据进行比对,比如一个tableA 4条,一个tableB 5条,那就是比对4*5 = 20次
而先筛选一次的话,就是意味着先对tableB筛选,筛选出3条,然后在对tableA筛选,5+4 = 9次 数据量小还无所谓,那数量大的话。。。。
三、where条件后面的筛选条件位置有影响
mysql where 执行顺序从左到右 也就意味着把过滤效果最大的放在最上面或者说靠where越近
oracle where 执行顺序从右到左 也就意味着把过滤效果最大的放在最下面或者说靠where越远
表的位置也符合这规律(表位置没试过,网上说的)
四、查询列时,尽量不用* 用具体的参数,以前写代码图方便经常写个* ,其实有的时候根本用不到那么多属性,所以查的少当然快点咯
如: select * from tableA
改成:select name,code from tableA
五、如果表加了索引的字段,书写值一定要规范,如例子虽然也能查出正确的结果,不过此时该字段查询索引未生效,所以还是稍微麻烦点打上‘’
如:select code from tableB where status = 2 (表字段status为char类型)
修改:select code from tableB where status = '2'
六、从表的方面可以把需要筛选的字段加上索引,效果就像开了挂一样哈哈,反正我的语句我觉得就是索引加的从一分钟到了20秒,个人觉得这个很好用
以上就是本次优化性能用到的方法,不过影响性能的不仅仅是这些方面,比如还有数据库本身的影响,我们的数据库是开发用的16G mysql,总而言之每个地儿都扣点,性能当然快很多了,积水成渊嘛。额,以上的想法只是本人本次试过的方法,有些原理可能还是漏洞百出(不过我确实快了。。),虽然40万数据其实也没多少,相比那些百万千万,甚至亿级的,抱歉我还很菜,这种的找我老大,我还是咸鱼一条。