最近遇到一个专门进行SQL技术优化的项目,对很多既有的老存储过程进行调优(现在已经不再新增任何存储过程),因此系统的对SQL语句编写进行一次科学的学习变得很有必要。这儿将基于黄德承大神的Oracle SQL语句优化一书,选取其中比较实用和通用的部分进行介绍。
- 任何SQL语句,只要在where子句中实用了is null或is not null,那么Oracle优化器不会使用索引。
- 任何where子句的条件的左侧不能出现函数,否则不走索引,比如WHERE YEAR(createtime) = '2016',可以用createtime>='2016-01-01'
- 在使用通配符%的like语句中,可以通过like 'c%'使用索引
- order by语句,任何在order by语句的非索引项或者有计算表达式都将降低查询速度。
- NOT和<>,会造成不走索引,应该选择使用where price<200 or price > 100。
- IN和EXISTS,IN操作符的子查询都可以使用EXISTS代替,效率会高很多,where column in/exists (select 'X' from … where …),需要好好考虑。
Tip:
参数化SQL,like @count, '%'+ count +'%'
- 选择最优效率的表名顺序(Oracle解析器按照从右到左的顺序处理FROM子句中的表名),比如select count(*) from tab1 inner join tab2,这是优先检索表2,并将表2的数据与表1的合并。在SQL SERVER中,查看执行计划,发现并没有区别
- 减少查询的次数(包括对表查询),将多个分离的查询合并
- 能够在WHERE字句中使用的条件,尽量避免放在HAVING字句中
- 用EXISTS替代IN,用表连接替代EXISTS
- 用EXISTS替代DISTINCT,因为RDBMS会在子查询条件满足后立即返回结果
- 用索引来提高效率,定期的重构索引是有必要的
- 避免在索引列上计算
- 用>=代替>
- 注意隐式转换
- UNION-ALL替换UNION
- 在严格遵守条件的情况下(所有的列必须包含在相同的索引中并保持在索引中的排列顺序,所有的列必须定义为非空),ORDER BY子句也是可以走索引的。