oracle sql 优化(三)

(23) 用>=替代> sql

高效: 数据库

SELECT * FROM EMP WHERE DEPTNO >=4

低效: 函数

SELECT * FROM EMP WHERE DEPTNO >3

二者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录然后者将首先定位到DEPTNO=3的记录而且向前扫描到第一个DEPT大于3的记录.优化

  (24) 用UNION替换OR (适用于索引列) spa

    一般状况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将形成全表扫描. 注意, 以上规则只针对多个索引列有效. 若是有column没有被索引, 查询效率可能会由于你没有选择OR而下降. 在下面的例子中, LOC_ID 和REGION上都建有索引. code

高效:排序

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, 那就须要返回记录最少的索引列写在最前面. 
内存

  (25) 用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);

  

(26) 避免在索引列上使用IS NULL和IS NOT NULL 

    避免在索引中使用任何能够为空的列,ORACLE将没法使用该索引.对于单列索引,若是列包含空值,索引中将不存在此记录. 对于复合索引,若是每一个列都为空,索引中一样不存在此记录. 若是至少有一个列不为空,则记录存在于索引中.举例: 若是惟一性索引创建在表的A列和B列上, 而且表中存在一条记录的A,B值为(123,null) , ORACLE将不接受下一条具备相同A,B值(123,null)的记录(插入). 然而若是全部的索引列都为空,ORACLE将认为整个键值为空,而空不等于空. 所以你能够插入1000 条具备相同键值的记录,固然它们都是空! 由于空值不存在于索引列中,因此WHERE子句中对索引列进行空值比较将使ORACLE停用该索引. 

低效: (索引失效)

SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;

高效: (索引有效)

SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;

(27) 老是使用索引的第一个列: 

    若是索引是创建在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引. 这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引

(28) 用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'

(29) 用WHERE替代ORDER BY: 
ORDER BY 子句只在两种严格的条件下使用索引. 
ORDER BY中全部的列必须包含在相同的索引中并保持在索引中的排列顺序. 
ORDER BY中全部的列必须定义为非空. 
WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列. 
例如: 表DEPT包含如下列: 
DEPT_CODE PK NOT NULL 
DEPT_DESC NOT NULL 
DEPT_TYPE NULL 
低效: (索引不被使用)

SELECT DEPT_CODE FROM DEPT ORDER BY DEPT_TYPE

高效: (使用索引)

SELECT DEPT_CODE FROM DEPT WHERE DEPT_TYPE > 0

(30) 避免改变索引列的类型.: 
    当比较不一样数据类型的数据时, ORACLE自动对列进行简单的类型转换. 
假设 EMPNO是一个数值类型的索引列. SELECT … FROM EMP WHERE EMPNO = ‘123' 实际上,通过ORACLE类型转换, 语句转化为: SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(‘123') 幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变. 如今,假设EMP_TYPE是一个字符类型的索引列. SELECT … FROM EMP WHERE EMP_TYPE = 123 这个语句被ORACLE转换为: SELECT … FROM EMP WHERETO_NUMBER(EMP_TYPE)=123 由于内部发生的类型转换, 这个索引将不会被用到! 为了不ORACLE对你的SQL进行隐式的类型转换, 最好把类型转换用显式表现出来. 注意当字符和数值比较时, ORACLE会优先转换数值类型到字符类型 

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

(32) a. 若是检索数据量超过30%的表中记录数.使用索引将没有显著的效率提升. 
b. 在特定状况下, 使用索引也许会比全表扫描慢, 但这是同一个数量级上的区别. 而一般状况下,使用索引比全表扫描要块几倍乃至几千倍! 

(33) 避免使用耗费资源的操做: 
    带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 执行耗费资源的排序(SORT)功能. DISTINCT须要一次排序操做, 而其余的至少须要执行两次排序. 一般, 带有UNION, MINUS , INTERSECT的SQL语句均可以用其余方式重写. 若是你的数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS, INTERSECT也是能够考虑的, 毕竟它们的可读性很强(Oracle查询运算:intersect和minus intersect运算 返回查询结果中相同的部分 exp:各个部门中有哪些相同的工种 select job from account intersect select job from research intersect select job from sales; minus运算 返回在第一个查询结果中与第二个查询结果不相同的那部分行记录。 有哪些工种在财会部中有,而在销售部中没有)

(34) 优化GROUP BY: 
    提升GROUP BY 语句的效率, 能够经过将不须要的记录在GROUP BY 以前过滤掉.下面两个查询返回相同结果但第二个明显就快了许多. 
低效: 

SELECT JOB , AVG(SAL)
FROM EMP GROUP JOB HAVING JOB = ‘PRESIDENT' OR JOB = ‘MANAGER'

高效:

SELECT JOB , AVG(SAL)
FROM EMP
WHERE JOB = ‘PRESIDENT'
OR JOB = ‘MANAGER' GROUP JOB
相关文章
相关标签/搜索