SQL性能优化
数据库业务系统的核心是数据库和数据,据说,80%的性能问题都是由不良的SQL语句引起的,比如:通过增加一个索引、改变SQL语句的连接方法可以极大的改变系统的性能;但SQL语句的优化是一个笼统的概念,难以掌握,但遵守一些规则有助于提高整体性能,下面是一些参考建议。
1.FROM子句中的解析顺序(只在基于规则的优化器中有效)
Oracle的解析器是按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表称为基础表(driving table),将被最先处理;在FROM子句中包含多个表的情况下,建议选择记录最少的表作为基础表;若有3张以上的表连接查询,建议选择交叉表(intersection table)作为基础表,交叉表是指那个被其他表所引用的表。
2.WHERE子句中的连接顺序
Oracle的解析器采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的最
后。
3.SELECT子句中避免使用*
Oracle在解析的过程中,会将*号依次转换成所有的列名,这个工作是通过查询数据字典完成的,这将耗费更多的时间与资源。
4.使用Decode函数
使用Decode函数可以避免重复扫描相同记录或重复连接相同的表,减少了I/O和处理时间。
5.用Truncate替代Delete
当确定要删除表中所有记录时,使用Truncate代替Delete。
Delete操作,回滚段用来存放被删除的信息,若没有Commit事务,Oracle可根据这些信息恢复数据。
Truncate操作,回滚段不再存放任何可被恢复的信息,当命令运行后,数据不能被恢复,因此很少使用资源,执行时间也很快。
6.尽量多使用Commit
只要有可能,在程序中尽量多使用Commit,这样程序的性能得到提高,需求也会因为Commit所释放的资源而减少。Commit所释放的资源:
――回滚段上用于恢复数据的信息
――被程序语句获得的锁
――redo log buffer 中的空间
――Oracle为管理上述3种资源中的内部花费
7.用Where子句替换Having子句
避免使用Having子句,Having只会在检索出所有记录之后才对结果集进行过滤,这个处理
需要排序、汇总等操作,如果能通过Where子句限制记录的数目,则减少了这方面的开销。
8.通过内部函数提高SQL效率
复杂的SQL往往牺牲了执行效率,如果内部函数能实现其功能,尽量使用内部函数。
9.使用表的别名(Alias)
当在SQL语句中连接多个表时,使用表的别名并把别名前缀于每个Column上,这样可以减少解析的时间并减少那些由Column歧义引起的语法错误。
10.用Exists替代In、用Not Exists替代Not In
在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接,在这种情况下,使用Exists(或Not Exists)通常会提高查询的效率。
在子查询中,Not In子句将执行一个内部的排序和合并,因为它对子查询中的表执行了一个全表遍历,所以效率低下,为了避免使用Not In,可以把它改写成外连接(Outer Joins)或N
ot Exists。
(高效)
SELECT * FROM EMP (基础表) WHERE EMPNO > 0
AND EXISTS (SELECT ‘X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB')
(低效)
SELECT * FROM EMP (基础表) WHERE EMPNO > 0
AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB')
11.定期重构索引
频繁的添加、删除操作会导致索引效率低下,定期的重构索引是有必要的。
12.sql语句用大写的
因为oracle总是先解析sql语句,把小写的字母转换成大写的再执行
13.避免在索引列上使用计算
WHERE子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描.
低效: SELECT … FROM DEPT WHERE SAL * 12 > 25000;
高效:SELECT … FROM DEPT WHERE SAL > 25000/12;
14.用>=替代>
两者的区别在于,前者DBMS将直接跳到第一个DEPT等于4的记录,而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录。
高效: SELECT * FROM EMP WHERE DEPTNO >=4
低效: SELECT * FROM EMP WHERE DEPTNO >3
15.用IN来替换OR
这条规则实际的执行效果有待检验,在ORACLE8i下,两者的执行路径似乎是相同的。
低效:SELECT… FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30
高效:SELECT… FROM LOCATION WHERE LOC_IN IN (10,20,30);
16.避免改变索引列的类型
当比较不同数据类型的数据时,ORACLE自动对列进行简单的类型转换。
假设 EMPNO是一个数值类型的索引列.
SELECT … FROM EMP WHERE EMPNO = ‘123'
实际上,经过ORACLE类型转换, 语句转化为:
SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(‘123')
17. 需要当心的WHERE子句
某些SELECT 语句中的WHERE子句不使用索引,如:
sql语句优化方式 (1) !=将不使用索引,索引只能告诉你什么存在于表中,而不能告诉你什么不存在于表中
(2) ||是字符连接函数. 就象其他函数那样,停用了索引
(3) +是数学函数. 就象其他数学函数那样,停用了索引
18. 数据量的考虑
若检索数据量超过表中总记录数的20%(估计值),则全表扫描,即使使用索引也没显著的效率提高。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论