`

SQL性能优化

 
阅读更多

1选用适合的ORACLE优化器
ORACLE的优化器共有3:
   a.  RULE (基于规则)   b. COST (基于成本)  c. CHOOSE (选择性)

   设置缺省的优化器,可以通过对init.ora文件中OPTIMIZER_MODE参数的各种声明,RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS . 你当然也在SQL句级或是会话(session)级对其进行覆盖.
   为了使用基于成本的优化器(CBO, Cost-Based Optimizer) , 你必须经常运行analyze 命令,以增加数据库中的对象统计信息(object statistics)的准确性.
   如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的优化器模式将和是否运行过analyze命令有关如果table已经被analyze优化器模式将自动成为CBO , 反之,数据库将采用RULE形式的优化器.
   在缺省情况下,ORACLE采用CHOOSE优化器为了避免那些不必要的全表扫描(full table scan) , 你必须尽量避免使用CHOOSE优化器,而直接采用基于规则或者基于成本的优化器.

2访问Table的方式
ORACLE 采用两种访问表中记录的方式:
a.全表扫描
       全表扫描就是顺序地访问表中每条记录. ORACLE采用一次读入多个数据块(database block)的方式优化全表扫描.
   
b.通过ROWID访问表
       你可以采用基于ROWID的访问方式情况,提高访问表的效率, , ROWID包含了表中记录的物理位置信息..ORACLE采用索引(INDEX)实现了数据和存放数据的物理位置(ROWID)之间的联系通常索引提供了快速访问ROWID的方法,因此那些基于索引列的查询就可以得到性能上的提高

3共享SQL语句
为了不重复解析相同的SQL语句,在第一次解析之后, ORACLESQL语句存放在内存中.这块位于系统全局区域SGA(system global area)的共享池(shared buffer pool)中的内存可以被所有的数据库用户共享因此,当你执行一个SQL语句(有时被称为一个游标),如果它和之前的执行过的语句完全相同, ORACLE就能很快获得已经被解析的语句以及最好的
执行路径. ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用.
     可惜的是ORACLE只对简单的表提供高速缓冲(cache buffering) ,这个功能并不适用于多表连接查询.数据库管理员必须在init.ora中为这个区域设置合适的参数,当这个内存区域越大,就可以保留更多的语句,当然被共享的可能性也就越大了.
当你向ORACLE 提交一个SQL语句,ORACLE会首先在这块内存中查找相同的语句.
 这里需要注明的是,ORACLE对两者采取的是一种严格匹配,要达成共享,SQL语句必须
完全相同(包括空格,换行等).
     共享的语句必须满足三个条件:
A.字符级的比较:
当前被执行的语句和共享池中的语句必须完全相同(sql语句的大小写、中间的空格都要完全相同。)
B. 两个语句所指的对象必须完全相同
C. 两个SQL语句中必须使用相同的名字的绑定变量(bind variables)
比如,下面两个SQL语句就不一样:
select pin , name from people where pin = :blk1.ot_ind;
select pin , name from people where pin = :blk1.ov_ind;

4EXISTS替代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)
5NOT 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);

6用表连接替换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’ ;
7EXISTS替换DISTINCT
当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT. 一般可以考虑用EXIST替换

例如:
低效:
    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);

  EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果.

8选择最有效率的表名顺序(只在基于规则的优化器中有效)
ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.ORACLE处理多个表时会运用排序及合并的方式连接它们.首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并.
如果有3个以上的表连接查询那就需要选择交叉表(intersection table)作为基础表交叉表是指那个被其他表所引用的表.
9. WHERE子句中的连接顺序.
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.
10. SELECT子句中避免使用"*"
当你想在SELECT子句中列出所有的COLUMN,使用动态SQL列引用"*"是一个方便的方法.不幸的是,这是一个非常低效的方法实际上,ORACLE在解析的过程中会将*’ 依次转换成所有的列名这个工作是通过查询数据字典完成的这意味着将耗费更多的时间

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

DELETE FROM EMP E
WHERE E.ROWID > (SELECT MIN(X.ROWID)
                   FROM EMP X
                   WHERE X.EMP_NO = E.EMP_NO);
12TRUNCATE替代DELETE
13尽量多使用COMMIT
14计算记录条数
     和一般的观点相反, count(*) count(1)稍快 当然如果可以通过索引检索,对索引列的计数仍旧是最快的例如 COUNT(EMPNO)
15Where子句替换HAVING子句
     避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤这个处理需要排序,总计等操作如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销.

16 用IN来替换OR
下面的查询可以被更有效率的语句替换:
低效:
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);
17避免在索引列上使用IS NULLIS NOT NULL
18总是使用索引的第一个列
如果索引是建立在多个列上只有在它的第一个列(leading column)where子句引用时,优化器才会选择使用该索引.
SQL> create table multiindexusage ( inda number , indb number , descr varchar2(10));
Table created.
SQL> create index multindex on multiindexusage(inda,indb);
Index created.
SQL> set autotrace traceonly

SQL>  select * from  multiindexusage where inda = 1;
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'MULTIINDEXUSAGE'
   2    1     INDEX (RANGE SCAN) OF 'MULTINDEX' (NON-UNIQUE)

SQL> select * from  multiindexusage where indb = 1;
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   TABLE ACCESS (FULL) OF 'MULTIINDEXUSAGE'
  
很明显当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引

19WHERE替代ORDER BY
ORDER BY 子句只在两种严格的条件下使用索引.

ORDER BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序.
ORDER BY中所有的列必须定义为非空.

WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列.
20使用日期
当使用日期是,需要注意如果有超过5位小数加到日期上这个日期会进到下一天!
例如:
a.
SELECT TO_DATE(01-JAN-93+.99999)
FROM DUAL;
Returns:
   ’01-JAN-93 23:59:59
b.
SELECT TO_DATE(01-JAN-93+.999999)
FROM DUAL;
Returns:
   ’02-JAN-93 00:00:00

21使用显式的游标(CURSORs)
使用隐式的游标,将会执行两次操作第一次检索记录第二次检查TOO MANY ROWS 这个exception . 而显式游标不执行第二次操作.

<!--EndFragment-->
分享到:
评论

相关推荐

    ORACLE SQL性能优化系列

    ORACLE SQL性能优化系列 ORACLE SQL性能优化是数据库管理员和开发者非常关心的一个话题。为了提高数据库的性能,ORACLE 提供了多种优化技术。下面我们将详细介绍 ORACLE SQL 性能优化系列中的一些重要知识点。 一...

    SQL性能优化解决方案

    在SQL性能优化领域,数据库的高效运行至关重要。"SQL性能优化解决方案"着重关注如何发现并解决数据库系统的性能问题,这不仅涉及查询效率,还包括数据处理、存储和并发控制等多个方面。下面将详细介绍如何进行SQL...

    sql性能优化

    sql性能优化、sql性能优化、sql性能优化、sql性能优化

    sql 性能优化文档下载

    在IT行业中,SQL性能优化是数据库管理的关键环节,它直接影响到系统的响应速度和整体效率。以下将详细讨论SQL性能优化的一些关键知识点,结合提供的文件名,我们主要关注Oracle数据库的相关内容。 1. **理解SQL语句...

    sql性能优化十大要素(英文)

    本文档《sql性能优化十大要素》详细介绍了在DB2环境下,如何优化SQL语句的性能。文档作者是Sheryl M. Larsen,通过十条具体建议来实现SQL的高效执行,这些要素对于数据库管理员(DBA)、开发人员,以及任何使用关系...

    SQL性能优化调整.ppt

    《SQL性能优化调整》 SQL性能优化是数据库管理中至关重要的一环,特别是在Oracle数据库系统中。Oracle数据库在处理SQL查询时有一套详细的执行步骤,旨在提高查询效率和系统整体性能。 1. **编译阶段**: - **共享...

    ORACLE_SQL性能优化(全).ppt

    【Oracle SQL性能优化】 Oracle SQL性能优化是数据库开发人员必须掌握的关键技能,它涉及到SQL语句的编写、执行过程、优化器的选择以及执行计划的分析等多个方面。在Oracle数据库环境中,优化SQL性能对于提升系统...

    SQL 性能优化工具

    SQL性能优化是一个重要的主题,尤其是在使用像SQL Server 2000这样的早期版本时,由于资源有限,优化显得更为关键。本系列课程主要关注通过理解并应用锁和事务管理来提升SQL查询的效率。 首先,我们要了解【锁和锁...

    SQL性能优化以及索引的优化

    在数据库管理领域,SQL性能优化和索引优化是至关重要的技术环节,它们直接影响到数据库的运行效率和用户体验。本文将深入探讨这两个主题,提供丰富的知识和实践经验。 首先,SQL性能优化涉及一系列策略和技巧,旨在...

    Oracle+SQL性能优化40条.docx

    Oracle SQL 性能优化 40 条 以下是 Oracle SQL 性能优化 40 条的知识点总结: 一、SQL 语句执行步骤 * 语法分析:检查 SQL 语句的语法正确性 * 语义分析:分析 SQL 语句的逻辑含义 * 视图转换:将 SQL 语句转换为...

    《oracle SQL性能优化》中文电子书

    《Oracle SQL性能优化》这本书是数据库管理员和开发人员的重要参考资料,它深入探讨了如何提高Oracle数据库的SQL查询性能。在数据库系统中,SQL查询的速度直接影响到应用的响应时间和整体性能,因此,理解并掌握SQL...

    ORACLE-SQL性能优化大全.pdf

    ### ORACLE-SQL性能优化大全知识点详述 #### 一、优化基础知识概述 - **性能管理**: - **尽早开始**:性能优化应该在项目的早期就开始考虑,而不是等到后期出现性能瓶颈时才去处理。 - **设立合适目标**:设定...

    JAVA\ORACLE_SQL性能优化(全).ppt

    【SQL性能优化基础】 在Java或Oracle SQL性能优化中,首要任务是对SQL语句有深入的理解,以便在编程时能够写出高效运行的代码。优化基础知识包括性能管理、SQL优化机制和应用调整等。 1. **性能管理** - **尽早...

    ORACLESQL性能优化系列[参考].pdf

    Oracle SQL性能优化是数据库管理中的重要环节,直接影响到应用程序的响应速度和整体系统效率。本文主要探讨了两个关键方面:优化器的选择和访问表的方式。 首先,Oracle 提供了三种优化器供选择:RULE、COST 和 ...

    Oracle_SQL性能优化.

    Oracle_SQL性能优化.

    Oracle数据库SQL性能优化

    Oracle数据库SQL性能优化学习可以用到的。

    ORACLESQL性能优化.pptx

    Oracle SQL 性能优化 Oracle SQL 性能优化是数据库管理中非常重要的一环。通过对 SQL 语句执行的过程、Oracle 优化器、表之间的关联、如何得到 SQL 执行计划、如何分析执行计划等内容的讨论,可以逐步掌握 SQL ...

    Sql Server——Sql性能优化

    Sql Server——Sql性能优化Sql Server——Sql性能优化Sql Server——Sql性能优化Sql Server——Sql性能优化Sql Server——Sql性能优化Sql Server——Sql性能优化Sql Server——Sql性能优化Sql Server——Sql性能优化

Global site tag (gtag.js) - Google Analytics