最近在做一个报表,通过一个sql把需要的数据全都查出来,sql涉及到一点业务,比较复杂些,各种左右内连接,分页查询速度都特别慢都得3秒多,这对用户来说实在是太不友好了,于是趁着表改造,我就重新看着怎么能优化这个sql,终于,将查询控制在了0.3秒左右,所以尤其对于复杂一点的sql来说,了解一些sql的基本优化是多么重要的事,下面总结一下此次优化sql的经验和新得(以后再有sql优化方案,就接这篇往下写):
1、首先sql语句用大写,查询结果不要使用*,表关联时取别名
2、考虑使用“临时表”暂存中间结果(进行表关联数据拆分,即先查出核心数据,再通过核心数据查其他数据,这样会快得多)
多张表关联查询时,可以将主表根据条件先过滤一遍,放入临时表中,其它表关联时就关联这张临时表,而且如果其他表都是依靠主表的话,分页这一步就可以在临时表中完成,更可以加快效率。而且使用临时表也可以使sql看起来简洁易懂,但是,临时表的好处远远不止这些,将临时结果暂存在临时表,后面的查询就在tempdb中了,这可以避免程序中多次扫描主表,也大大减少了程序执行中“共享锁”阻塞“更新锁”,减少了阻塞,提高了并发性能。
3、用EXISTS替换DISTINCT
在一对多表查询根据条件去除冗余数据时,可以使用EXISTS替换DISTINCT;
(低效):
SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E WHERE D.DEPT_NO = E.DEPT_NO
(高效):
SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT 1 FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
4、用UNION替换OR (适用于索引列)
通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描
5、GROUP BY优化
通过将不需要的记录在GROUP BY 之前过滤掉,其实换句话说就是,如非必要,使用WHERE替换HAVING
6、IN替换OR,EXISTIS替换IN
7、查询条件减少使用函数,避免全表扫描
8、有些数据操作的业务逻辑可以放到应用层进行实现
上面的那个报表业务上的大都是sql去实现,原因是这个需求涉及到分页,分页的话sql实现还是很快的,但是如果是查一些数据不涉及分页且业务很复杂的话,还是推荐使用代码实现,因为这样好维护,而且内存处理数据也是特别快的,有时候甚至比写的很复杂的sql效果好的多
9、inner关联的表可以先查出来,再去关联 left join 的表