数据库SQL性能优化

 

1.in与exists的效率比较sql

in是把外表和内表做hash 链接,而exists 是对外表做loop 循环,每次loop 循环再对内表进行查询。一直以来认为exists 比in 效率高的说法是不许确的。若是查询的两个表大小至关,那么用in 和exists 差异不大。数据库

若是两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:oracle

例如:函数

表A(小表),表B(大表)1:oop

select * from A where cc in (select cc from B)效率低,用到了A 表上cc 列的索引;post

select * from A where exists(select cc from B where cc=A.cc)效率高,用到了B 表上cc 列的索引。性能

 

2.not in 和not exists大数据

若是查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;优化

而not extsts 的子查询依然能用到表上的索引。因此不管那个表大,用not exists 都比not in 要快。spa

 

3.is null 和is not null的比较

索引列是不容许有null值的,也就是说若是某列存在空值,即便对该列建索引也不会提升性能。推荐方案:用其它相同功能的操做运算代替,如:a is not null 改成 a>0 或a>’ ’等。不容许字段为空,而用一个缺省值代替空值,如申请中状态字段不容许为空,缺省为申请。

 

4.LIKE操做符 

用YW_YHJBQK表中营业编号后面的户标识号可来查询营业编号 YY_BH LIKE ‘%5400%’ 这个条件会产生全表扫描,这种查询不会引用索引,若是改为YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 则会利用YY_BH的索引进行两个范围的查询,性能确定大大提升。

 

5.union操做符

union在进行表连接后会筛选掉重复的记录,因此在表连接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录:最多见的是过程表与历史表UNION。如:

select * from gc_dfys 
union 
select * from ls_jg_dfys
这个SQL在运行时先取出两个表的结果,再用排序空间进行排序删除重复的记录,最后返回结果集,若是表数据量大的话可能会致使用磁盘进行排序。
推荐方案:采用UNION ALL操做符替代UNION,由于UNION ALL操做只是简单的将两个结果合并后就返回。
 
6.联接列,对于有联接的列,即便最后的联接值为一个静态值,优化器是不会使用索引的。咱们一块儿来看一个例子,假定有一个职工表(employee),对于一个职工的姓和名分红两列存放(FIRST_NAME和LAST_NAME),如今要查询一个叫比尔.克林顿(Bill Cliton)的职工。
select * from employss where first_name|| '' ||last_name = 'Beill Cliton' ;这样的话系统优化器对基于last_name建立的索引没有使用。
 
7.order by
ORDER BY语句决定了Oracle如何将返回的查询结果排序。Order by语句对要排序的列没有什么特别的限制,也能够将函数加入列中(象联接或者附加等)。任何在Order by语句的非索引项或者有计算表达式都将下降查询速度。仔细检查order by语句以找出非索引项或者表达式,它们会下降性能。解决这个问题的办法就是重写order by语句以使用索引,也能够为所使用的列创建另一个索引,同时应绝对避免在order by子句中使用表达式。
 
8.where子句后的条件顺序对大数据量表查询产生直接影响
Select * from zl_yhjbqk where dy_dj = '1KV如下' and xh_bz=1 
Select * from zl_yhjbqk where xh_bz=1 and dy_dj = '1KV如下'
以上两个SQL中dy_dj(电压等级)及xh_bz(销户标志)两个字段都没进行索引,因此执行的时候都是全表扫描,第一条SQL的dy_dj = ’1KV如下’条件在记录集内比率为99%,而xh_bz=1的比率只为0.5%,在进行第一条SQL的时候99%条记录都进行dy_dj及xh_bz的比较,而在进行第二条SQL的时候0.5%条记录都进行dy_dj及xh_bz的比较,以此能够得出第二条SQL的CPU占用率明显比第一条低。
 
9.采用函数处理的字段不能利用索引,如:
substr(hbs_bh,1,4)=’5400’,优化处理:hbs_bh like ‘5400%’
trunc(sk_rq)=trunc(sysdate), 优化处理:sk_rq>=trunc(sysdate) and sk_rq<trunc(sysdate+1)
进行了显式或隐式的运算的字段不能进行索引,如:ss_df+20>50,优化处理:ss_df>30
‘X’ || hbs_bh>’X5400021452’,优化处理:hbs_bh>’5400021542’
sk_rq+5=sysdate,优化处理:sk_rq=sysdate-5
条件内包括了多个本表的字段运算时不能进行索引,如:
ys_df>cx_df,没法进行优化 
qc_bh || kh_bh=’5400250000’,优化处理:qc_bh=’5400’ and kh_bh=’250000’
 
10.ORACLE 的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最早处理,在FROM子句中包含多个表的状况下,你必须选择记录条数最少的表做为基础表。若是有3个以上的表链接查询, 那就须要选择交叉表(intersection table)做为基础表, 交叉表是指那个被其余表所引用的表
 
11. WHERE子句中的链接顺序:

ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的链接必须写在其余WHERE条件以前, 那些能够过滤掉最大数量记录的条件必须写在WHERE子句的末尾.

12. SELECT子句中避免使用 ‘ * ‘:ORACLE在解析的过程当中, 会将’*’ 依次转换成全部的列名, 这个工做是经过查询数据字典完成的, 这意味着将耗费更多的时间。

13.减小访问数据库的次数:ORACLE在内部执行了许多工做: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等。

14.在SQL*Plus , SQL*Forms和Pro*C中从新设置ARRAYSIZE参数, 能够增长每次数据库访问的检索数据量 ,建议值为200。

15. 整合简单,无关联的数据库访问:若是你有几个简单的数据库查询语句,你能够把它们整合到一个查询中(即便它们之间没有关系) 。

16. 删除重复记录:最高效的删除重复记录方法 ( 由于使用了ROWID)例子:DELETE  FROM  EMP E  WHERE  E.ROWID > (SELECT MIN(X.ROWID) FROM  EMP X  WHERE  X.EMP_NO = E.EMP_NO)。

17. 用TRUNCATE替代DELETE:

18. 尽可能多使用COMMIT

COMMIT所释放的资源:

a. 回滚段上用于恢复数据的信息.

b. 被程序语句得到的锁

c. redo log buffer 中的空间

19.用where替换having子句,避免使用HAVING子句, HAVING 只会在检索出全部记录以后才对结果集进行过滤. 这个处理须要排序,总计等操做.若是能经过WHERE子句限制记录的数目,那就能减小这方面的开销. (非oracle中)on、where、having这三个均可以加条件的子句中,on是最早执行where次之,having最后.由于on是先把不符合条件的记录过滤后才进行统计,它就能够减小中间运算要处理的数据,按理说应该速度是最快的,where也应该比having快点的,由于它过滤数据后才进行sum,在两个表联接时才用on的,因此在一个表的时候,就剩下where跟having比较了.在这单表查询统计的状况下,若是要过滤的条件没有涉及到要计算字段,那它们的结果是同样的,只是where可使用rushmore技术,而having就不能,在速度上后者要慢若是要涉及到计算的字 段,就表示在没计算以前,这个字段的值是不肯定的,根据上篇写的工做流程,where的做用时间是在计算以前就完成的,而having就是在计算后才起做 用的,因此在这种状况下,二者的结果会不一样。在多表联接查询时,on比where更早起做用。系统首先根据各个表之间的联接条件,把多个表合成一个临时表 后,再由where进行过滤,而后再计算,计算完后再由having进行过滤。因而可知,要想过滤条件起到正确的做用,首先要明白这个条件应该在何时起做用,而后再决定放在那里。

20.使用表的别名(Alias)当在SQL语句中链接多个表时, 请使用表的别名并把别名前缀于每一个Column上.这样一来,就能够减小解析的时间并减小那些由Column歧义引发的语法错误。

21. 用索引提升效率:

22.用>=替代>
23. 用UNION替换OR (适用于索引列)
24.用where代替order by
低效: (索引不被使用) 
SELECT DEPT_CODE FROM  DEPT  ORDER BY  DEPT_TYPE 
高效: (使用索引) 
SELECT DEPT_CODE  FROM  DEPT  WHERE  DEPT_TYPE > 0
25.优化GROUP BY提升GROUP BY 语句的效率, 能够经过将不须要的记录在GROUP BY 以前过滤掉.下面两个查询返回相同结果但第二个明显就快了许多.
低效: 
SELECT JOB , AVG (SAL) 
FROM EMP 
GROUP by JOB 
HAVING JOB = ‘PRESIDENT
OR JOB = ‘MANAGER' 
高效: 
SELECT JOB , AVG (SAL) 
FROM EMP 
WHERE JOB = ‘PRESIDENT
OR JOB = ‘MANAGER' 
GROUP by JOB
相关文章
相关标签/搜索