SQL优化的一些实用方法

一、任何在where子句中使用is null或is not null的语句优化器是不容许使用索引的。由于只有该字段中有null值,即便建立了索引其实也
是没有用的,因此建立索引应该在有值的字段上建立;sql

二、使用该sql语句将不会使用索引:select * from employee where last_name like ‘%cliton%';
   这样的话会使用索引:     select * from employee where last_name like ‘cliton%';数据库

三、Order by语句
ORDER BY语句决定了Oracle如何将返回的查询结果排序。Order by语句对要排序的列没有什么特别的限制,也能够将函数加入列中(象联接或
者附加等)。任何在Order by语句的非索引项或者有计算表达式都将下降查询速度。仔细检查order by语句以找出非索引项或者表达式,它们
会下降性能。解决这个问题的办法就是重写order by语句以使用索引,也能够为所使用的列创建另一个索引,同时应绝对避免在order by
子句中使用表达式。安全

四、 选择最有效率的表名顺序(只在基于规则的优化器中有效): 
ORACLE 的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最早处理,在FROM子句
中包含多个表的状况下,你必须选择记录条数最少的表做为基础表。若是有3个以上的表链接查询, 那就须要选择交叉表(intersection
table)做为基础表, 交叉表是指那个被其余表所引用的表. 网络

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

六、 减小访问数据库的次数,能使用一条sql语句查询出来的最好使用一条语句直接查询出来。  整合简单,无关联的数据库访问: 
若是你有几个简单的数据库查询语句,你能够把它们整合到一个查询中(即便它们之间没有关系) 函数

七、经过内部函数提升SQL效率.: 复杂的SQL每每牺牲了执行效率. 可以掌握上面的运用函数解决问题的方法在实际工做中是很是有意义的 性能

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

九、 用EXISTS替代IN、用NOT EXISTS替代NOT IN: 
在许多基于基础表的查询中,为了知足一个条件,每每须要对另外一个表进行联接.在这种状况下, 使用EXISTS(或NOT EXISTS)一般将提升查询的
效率. 在子查询中,NOT IN子句将执行一个内部的排序和合并. 不管在哪一种状况下,NOT IN都是最低效的 (由于它对子查询中的表执行了一个
全表遍历). 为了不使用NOT IN ,咱们能够把它改写成外链接(Outer Joins)或NOT EXISTS. 
例:
 (低效)select * from z_shangbiao u where u.ann_nnum!='' and u.ann_nnum  in( select e.user_account FROM  t_evaluation e)
(高效)select * from t_user u where u.account!='' and EXISTS( select e.user_account FROM  t_evaluation e where
u.account=e.user_account)lua

十、 用索引提升效率: 虽然使用索引能获得查询效率的提升,可是咱们也必须注意到它的代价. 索引须要空间来存储,也须要按期维护, 每
当有记录在表中增减或索引列被修改时, 索引自己也会被修改. 这意味着每条记录的INSERT , DELETE , UPDATE将为此多付出4 , 5 次的磁
盘I/O . 由于索引须要额外的存储空间和处理,那些没必要要的索引反而会使查询反应时间变慢.。按期的重构索引是有必要的.: 设计

十一、用EXISTS替换DISTINCT: 
当提交一个包含一对多表信息(好比部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT. 通常能够考虑用EXIST替换, EXISTS 使查
询更为迅速,由于RDBMS核心模块将在子查询的条件一旦知足后,马上返回结果. 例子: 
(低效): 
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 ‘X’ FROM  EMP E  WHERE E.DEPT_NO = D.DEPT_NO); 

十二、sql语句用大写的;由于oracle老是先解析sql语句,把小写的字母转换成大写的再执行 

1三、 避免在索引列上使用计算. 
WHERE子句中,若是索引列是函数的一部分.优化器将不使用索引而使用全表扫描. 
举例: 
低效: 
SELECT … FROM  DEPT  WHERE SAL * 12 > 25000; 
高效: 
SELECT … FROM DEPT WHERE SAL > 25000/12; 

1四、用>=替代> 
高效: 
SELECT * FROM  EMP  WHERE  DEPTNO >=4 
低效: 
SELECT * FROM EMP WHERE DEPTNO >3 

1五、 用UNION替换OR (适用于索引列) 
一般状况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将形成全表扫描. 注意, 以上规则只针对多个索引列有效.
若是有column没有被索引, 查询效率可能会由于你没有选择OR而下降. 在下面的例子中, LOC_ID 和REGION上都建有索引. 
高效: 
SELECT LOC_ID , LOC_DESC , REGION 
FROM LOCATION 
WHERE LOC_ID = 10 
UNION 
SELECT LOC_ID , LOC_DESC , REGION 
FROM LOCATION 
WHERE REGION = “MELBOURNE” 
低效: 
SELECT LOC_ID , LOC_DESC , REGION 
FROM LOCATION 
WHERE LOC_ID = 10 OR REGION = “MELBOURNE” 
若是你坚持要用OR, 那就须要返回记录最少的索引列写在最前面. 

1六、 老是使用索引的第一个列: 
若是索引是创建在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引. 这也是一条简单而重
要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引 
例:好比你建立了索引(account,age,classno)三个字段为索引,那么你的sql语句使用where的时候应该先使用account,此时才能使用索
引,若是你的where的第一个条件使用的是age或者classno那么将进行全表搜索,而忽略了索引。

1七、用UNION-ALL 替换UNION ( 若是有可能的话): 
当SQL 语句须要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 而后在输出最终结果前进行排序. 若是用UNION
ALL替代UNION, 这样排序就不是必要了. 效率就会所以获得提升. 须要注意的是,UNION ALL 将重复输出两个结果集合中相同记录. 所以各
位仍是要从业务需求分析使用UNION ALL的可行性. UNION 将对结果集合排序,这个操做会使用到SORT_AREA_SIZE这块内存. 对于这块内存的
优化也是至关重要的. 下面的SQL能够用来查询排序的消耗量 
低效: 
SELECT  ACCT_NUM, BALANCE_AMT 
FROM  DEBIT_TRANSACTIONS 
WHERE TRAN_DATE = ’31-DEC-95′ 
UNION 
SELECT ACCT_NUM, BALANCE_AMT 
FROM DEBIT_TRANSACTIONS 
WHERE TRAN_DATE = ’31-DEC-95′ 
高效: 
SELECT ACCT_NUM, BALANCE_AMT 
FROM DEBIT_TRANSACTIONS 
WHERE TRAN_DATE = ’31-DEC-95′ 
UNION ALL 
SELECT ACCT_NUM, BALANCE_AMT 
FROM DEBIT_TRANSACTIONS 
WHERE TRAN_DATE = ’31-DEC-95′ 

1八、避免改变索引列的类型.
好比age字段为int型,而后你查询的时候写的是 where age='13',虽然查询出来的结果是同样的可是效率会下降,由于数据库内部多作了个
操做,自动对字符123 进行TO_NUMBER(‘123′) 处理

1九、 须要小心的WHERE子句: 
某些SELECT 语句中的WHERE子句不使用索引. 这里有一些例子. 
在下面的例子里, (1)‘!=’ 将不使用索引. 记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中. (2) ‘||’是字符
链接函数. 就象其余函数那样, 停用了索引. (3) ‘+’是数学函数. 就象其余数学函数那样, 停用了索引. (4)相同的索引列不能互相比较,
这将会启用全表扫描. 

20、 优化GROUP BY,尽可能使用where代替having: 
提升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 

2一、不要使用SELECT *  这点不太容易作到。但是,若是在SELECT中指定你所须要的列,那将会带来如下的好处:  1 减小内存耗费和网络的带宽  2 你能够获得更安全的设计  3 给查询优化器机会从索引读取全部须要的列 

相关文章
相关标签/搜索