`

oracle sql优化

 
阅读更多

  Oracle 语句优化

1.        ORACLE 的解析器按照从右到左的顺序处理 FROM 子句中的表名,因此 FROM 子句中写在最后的表(基础表  driving table)将被最先处理。在 FROM 子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。

例如:

              TAB1 16384 条记录

             TAB2 1 条记录

           选择 TAB2作为基础表  (最好的方法)

           select count(*) from tab1tab2 执行时间 0.96

           选择 TAB2作为基础表  (不佳的方法)

           select count(*) from tab2tab1 执行时间 26.09

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

例如:

    (低效,执行时间 156.3)

    SELECT …  

    FROM EMP E  

    WHERE SAL > 50000  

    AND JOB = ‘MANAGER’  

    AND 25 < (SELECT COUNT(*) FROM EMP  

    WHERE MGR=E.EMPNO);

    (高效,执行时间 10.6)

    SELECT …  

    FROM EMP E  

       WHERE 25 < (SELECT COUNT(*) FROM EMP  

WHERE MGR=E.EMPNO)  

AND SAL > 50000  

AND JOB = ‘MANAGER’;

3.        SELECT子句中避免使用’*’

当你想在 SELECT子句中列出所有的 COLUMN时,使用动态 SQL列引用  ‘*’ 是一个方便的方法。不幸的是,这是一个非常低效的方法。实际上,ORACLE 在解析的过程中,会将‘*’ 依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间。

4.        使用DECODE 函数来减少处理时间, 使用 DECODE 函数可以避免重复扫描相同记录或重复连接相同的表。

5.        删除重复记录

最高效的删除重复记录方法  ( 因为使用了 ROWID)

DELETE FROM EMP E

WHERE E.ROWID > (SELECT MIN(X.ROWID)  

                         FROM EMP X

                         WHERE X.EMP_NO = E.EMP_NO);

6.        计算记录条数

和一般的观点相反,count(*) count(1)稍快,当然如果可以通过索引检索,对索

引列的计数仍旧是最快的。例如 COUNT(EMPNO)

7.        WHERE子句替换HAVING子句

避免使用 HAVING子句,HAVING 只会在检索出所有记录之后才对结果集进行过滤。 

这个处理需要排序,总计等操作。如果能通过 WHERE 子句限制记录的数目,那就能减少这方面的开销。

例如:

低效

SELECT REGIONAVG(LOG_SIZE)  

   FROM LOCATION  

   GROUP BY REGION  

   HAVING REGION REGION != ‘SYDNEY’

   AND REGION != ‘PERTH’

高效

SELECT REGIONAVG(LOG_SIZE)  

FROM LOCATION  

WHERE REGION REGION != ‘SYDNEY’  

AND REGION != ‘PERTH’  

GROUP BY REGION

HAVING 中的条件一般用于对一些集合函数的比较,如 COUNT() 等等。除此而外,一般的条件应该写在 WHERE 子句中。

8.        减少对表的查询

在含有子查询的 SQL语句中,要特别注意减少对表的查询。

例如:

低效

    SELECT TAB_NAME  

    FROM TABLES  

    WHERE TAB_NAME = ( SELECT TAB_NAME  

    FROM TAB_COLUMNS  

    WHERE VERSION = 604)  

    AND  DB_VER= ( SELECT DB_VER  

    FROM TAB_COLUMNS  

    WHERE VERSION = 604)

高效

    SELECT TAB_NAME  

    FROM TABLES  

    WHERE (TAB_NAME,DB_VER)  

    = ( SELECT TAB_NAME,DB_VER)  

    FROM TAB_COLUMNS  

    WHERE VERSION = 604)

9.        使用表的别名ALIAS

当在 SQL语句中连接多个表时,请使用表的别名并把别名前缀于每个 Column上。这

样一来,就可以减少解析的时间并减少那些由 Column歧义引起的语法错误。

(Column歧义指的是由于 SQL中不同的表具有相同的 Column名,当 SQL语句中出现这个 Column时,SQL解析器无法判断这个 Column的归属)

10.    EXISTS替代IN

在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。在这

种情况下,使用 EXISTS( NOT EXISTS)通常将提高查询的效率。

低效:

    SELECT *  

FROM EMP (基础表)  

WHERE EMPNO > 0  

AND DEPTNO IN (SELECT DEPTNO

FROM DEPT  

WHERE LOC = ‘MELB’)

    高效:

           SELECT *  

           FROM EMP (基础表)  

           WHERE EMPNO > 0  

           AND EXISTS (SELECT ‘X’  

           FROM DEPT  

           WHERE DEPT.DEPTNO = EMP.DEPTNO  

           AND LOC = ‘MELB’)

11.    NOT EXISTS替代 NOT IN

在子查询中, NOT IN子句将执行一个内部的排序和合并。  无论在哪种情况下, NOT IN都是最低效的  (因为它对子查询中的表执行了一个全表遍历)为了避免使用 NOT IN ,我们可以把它改写成外连接(Outer Joins) NOT EXISTS.

例如:

    SELECT …  

    FROM EMP  

    WHERE DEPT_NO NOT IN (SELECT DEPT_NO  

    FROM DEPT  

    WHERE DEPT_CAT=’A’);

    为了提高效率。改写为:

(方法一:高效)

    SELECT ….  

    FROM EMP A,DEPT B  

    WHERE A.DEPT_NO = B.DEPT(+)  

    AND B.DEPT_NO IS NULL  

    AND B.DEPT_CAT(+) = ‘A’

(方法二:最高效)

       SELECT ….  

    FROM EMP E

       WHERE NOT EXISTS (SELECT ‘X’  

FROM DEPT D  

WHERE D.DEPT_NO = E.DEPT_NO  

AND DEPT_CAT = ‘A’);  

12.    用表连接替换EXISTS

通常来说,采用表连接的方式比 EXISTS 更有效率

   SELECT ENAME  

    FROM EMP E  

    WHERE EXISTS (SELECT ‘X’  

    FROM DEPT  

    WHERE DEPT_NO = E.DEPT_NO  

    AND DEPT_CAT = ‘A’);

 (更高效)

    SELECT ENAME  

    FROM DEPT D,EMP E  

    WHERE E.DEPT_NO = D.DEPT_NO  

    AND DEPT_CAT = ‘A’ ;

13.    EXISTS替换DISTINCT

当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在 SELECT 子句

中使用 DISTINCT. 一般可以考虑用 EXIST 替换

例如:

低效:

    SELECT DISTINCT DEPT_NO,DEPT_N

    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);

14.    避免在索引列上使用计算

WHERE 子句中,如果索引列是函数的一部分。优化器将不使用索引而使用全表扫描。 

举例:

低效:

   SELECT …  

   FROM DEPT  

   WHERE SAL * 12 > 25000;

高效:

   SELECT …  

   FROM DEPT  

   WHERE SAL > 25000/12;

 :这是一个非常实用的规则,请务必牢记

15.    避免在索引列上使用NOT

通常,我们要避免在索引列上使用 NOTNOT 会产生在和在索引列上使用函数相同

的影响。当ORACLE“遇到”NOT,他就会停止使用索引转而执行全表扫描。

举例:

低效:  (这里,不使用索引)

    SELECT …  

    FROM DEPT  

    WHERE DEPT_CODE NOT = 0;

高效: (这里,使用了索引)

    SELECT …  

    FROM DEPT  

    WHERE DEPT_CODE > 0;

16.    >=替代>

如果 DEPTNO 上有一个索引,

高效:

    SELECT *  

    FROM EMP  

    WHERE DEPTNO >=4

低效:

    SELECT *  

    FROM EMP  

    WHERE DEPTNO >3

两者的区别在于,前者 DBMS将直接跳到第一个 DEPT 等于 4的记录而后者将首先

定位到 DEPTNO=3的记录并且向前扫描到第一个 DEPT 大于 3的记录。

17.    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那就需要返回记录最少的索引列写在最前面。

18.    IN来替换OR

下面的查询可以被更有效率的语句替换:

低效:

    SELECT…  

    FROM LOCATION  

    WHERE LOC_ID = 10  

    OR LOC_ID = 20  

    OR LOC_ID = 30

高效:

    SELECT…  

    FROM LOCATION  

    WHERE LOC_IN IN (102030);

:这是一条简单易记的规则,但是实际的执行效果还须检验,在 ORACLE8i 下,两者

的执行路径似乎是相同的。

19.    避免在索引列上使用IS NULLIS NOT NULL

避免在索引中使用任何可以为空的列,ORACLE 将无法使用该索引。对于单列索引,

如果列包含空值,索引中将不存在此记录。对于复合索引,如果每个列都为空,索引中同样不存在此记录。  如果至少有一个列不为空,则记录存在于索引中。

举例:

如果唯一性索引建立在表的 A列和 B 列上,  并且表中存在一条记录的 A B 值为(123null)   ORACLE 将不接受下一条具有相同 AB (123null)的记录(插入)然而如果所有的索引列都为空, ORACLE 将认为整个键值为空而空不等于空。  因此你可以插入 1000条具有相同键值的记录,当然它们都是空! 因为空值不存在于索引列中,所以 WHERE 子句中对索引列进行空值比较将使ORACLE 停用该索引。

举例:

低效:(索引失效)

    SELECT …  

    FROM DEPARTMENT       WHERE DEPT_CODE IS NOT NULL;

高效:(索引有效)

    SELECT …  

    FROM DEPARTMENT  

    WHERE DEPT_CODE >=0;

20.    UNION ALL替换 UNION( 如果有可能的话)

SQL语句需要 UNION两个查询结果集合时,这两个结果集合会以 UNION-ALL的方式被合并,然后在输出最终结果前进行排序。如果用 UNION ALL替代 UNION这样排序就不是必要了。效率就会因此得到提高。

举例:

低效:

    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’

:需要注意的是,UNION ALL 将重复输出两个结果集合中相同记录。因此各位还是

要从业务需求分析使用 UNION ALL 的可行性。UNION 将对结果集合排序,这个操作会使用到 SORT_AREA_SIZE这块内存。对于这块内存的优化也是相当重要的。下面的 SQL可以用来查询排序的消耗量

    Select substrname125  "Sort Area Name"

      substrvalue115    "Value"  

      from v$sysstat  

      where name like 'sort%'

21.    优化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

 

分享到:
评论

相关推荐

    oracle SQL优化技巧

    Oracle SQL 优化技巧 Oracle SQL 优化是提高数据库性能的关键技巧之一。以下是 Oracle SQL 优化的 12 个技巧: 1. 选择最有效率的表名顺序 在基于规则的优化器中,Oracle 的解析器按照从右到左的顺序处理 FROM ...

    Oracle SQL优化文档

    Oracle SQL优化文档提供了对Oracle数据库进行SQL语句优化的一系列方法和工具,旨在帮助数据库管理员和开发人员提高SQL查询性能和数据库效率。文档内容涵盖了从基本的SQL优化思路到具体的分析工具,详细介绍了如何...

    OracleSQL的优化.pdf

    Oracle SQL 优化 Oracle SQL 优化是数据库性能优化的关键部分。为了提高数据库的性能,我们需要从五个方面进行调整:去掉不必要的大型表的全表扫描、缓存小型表的全表扫描、检验优化索引的使用、检验优化的连接技术...

    oracle sql优化100条

    ### Oracle SQL优化100条概览 在Oracle数据库管理与优化领域,SQL查询的效率直接关系到系统性能和用户体验。以下将详细解读部分Oracle SQL优化原则,涵盖查询执行计划、表扫描方式、SQL语句优化及数据访问顺序等...

    Oracle SQL 优化与调优技术详解-附录:SQL提示

    在Oracle数据库中,SQL优化是一个至关重要的环节,它能够显著提高数据库查询的效率和性能。本文将详细介绍Oracle SQL中的“提示”(HINT)技术,这是Oracle SQL优化中使用的一项辅助手段,通过为查询提供额外的优化...

    oracle sql优化实战案例

    主要讲述oracle sql 的开发以及优化,对低效率的sql的优化方法和诊断技巧

    ORACLE SQL优化工具sqlhc

    Oracle SQL优化是数据库管理中的关键任务,用于提升查询性能,减少资源消耗,进而改善整体系统效率。`SQLHC`(SQL Health Check)是Oracle提供的一种实用工具,它可以帮助DBA(数据库管理员)诊断和优化SQL语句。在...

    落落 Oracle SQL优化与改写培训教程

    大量优化实战方法:将主要SQL优化点一一剖析,分享大量SQL优化的实际工作经验 50余改写调优案例:覆盖大多数DBA日常工作场景,具有相当大的实用价值 技巧+案例:可以作为DBA的参考手册,也可以作为开发人员编写SQL...

    Oracle sql优化.pdf

    Oracle SQL 优化 Oracle SQL 优化是指通过调整和优化 SQL 语句、数据库服务器设置和应用程序配置来提高数据库性能的过程。该过程涉及到多个方面,包括 SQL 语句优化、索引优化、数据库服务器配置优化、应用程序...

    ORACLE SQL 优化 存储过程 PROCEDURE

    ORACLE SQL 优化存储过程 PROCEDURE ORACLE SQL 优化存储过程 PROCEDURE 是一篇结合实际开发经验和理论知识的文章,旨在帮助开发者提高 SQL 开发效率和优化存储过程。文章涵盖了广泛的知识点,从基本的 SQL 语句到...

    Oracle SQL优化法则

    Oracle SQL优化是数据库管理的关键环节,它涉及到提升SQL语句执行效率,降低资源消耗,从而提高整体系统性能。以下是对Oracle SQL优化53个规则的详细解读,主要围绕选择优化器、访问表的方式、共享SQL语句这三大方面...

    oracle sql优化语句

    Oracle SQL 优化是数据库管理...总的来说,Oracle SQL优化涉及到对数据库行为的深入理解,包括优化器的工作原理、索引的使用策略以及执行计划的选择。通过恰当的配置和调优,可以大大提高数据库系统的性能和响应速度。

    oracle sql优化分享案例

    oracle sql案例的分享ppt,具体调优和改写sql的例子

    Oracle sql 优化实例

    不错的东东,通俗易懂,建议学习.赶紧下载吧

    oraclesql优化_Oracle中优化SQL的原则.pdf

    oraclesql优化_Oracle中优化SQL的原则.pdf

    大牛出手Oracle SQL优化实例讲解

    10.基于基本的优化CBO 11.如何统计数据库数据 12.Oracle如何统计操作系统数据 13./*+parallel(t,4)*/在大表查询性能的提现 14.CRAS和create insert的性能测试 15.增加字段时指定default值和先增加再update哪个性能好...

    OracleSQL优化初步

    在Oracle数据库管理中,SQL优化是一项至关重要的任务,它直接影响到数据库系统的性能和效率。"Oracle SQL优化初步"这个主题涵盖了DBA们在日常工作中必须掌握的基础知识和技巧。SQL优化的目标是通过改进查询结构、...

    高清完整版 Oracle 高性能SQL引擎剖析SQL优化与调优机制详解

    Oracle的SQL优化与调优机制复杂多样,涵盖了从SQL语句的编写、执行计划的选择、到资源管理的全方位调优方法。为了深入理解Oracle SQL优化与调优机制,需要掌握以下几个核心知识点。 首先,要掌握Oracle SQL的基本...

    Oracle SQL优化的53个黄金法则

    Oracle SQL优化是数据库管理中的关键任务,以确保高效的数据检索和整体系统性能。本文将深入探讨53个黄金法则中的几个关键原则,帮助你优化Oracle SQL查询。 1. **选择合适的优化器**: - ORACLE提供三种优化器:...

Global site tag (gtag.js) - Google Analytics