ORACLE SQL性能优化系列 (十二)

oracle|性能|优化

39.       总是使用索引的第一个列

如果索引是建立在多个列上, 只有在它的第一个列(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'

  

很明显, 当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引

 

 

40.       ORACLE内部操作

当执行查询时,ORACLE采用了内部的操作. 下表显示了几种重要的内部操作.

ORACLE Clause

内部操作

ORDER BY

SORT ORDER BY

UNION

UNION-ALL

MINUS

MINUS

INTERSECT

INTERSECT

DISTINCT,MINUS,INTERSECT,UNION

SORT UNIQUE

MIN,MAX,COUNT

SORT AGGREGATE

GROUP BY

SORT GROUP BY

ROWNUM

COUNT or COUNT STOPKEY

Queries involving Joins

SORT JOIN,MERGE JOIN,NESTED LOOPS

CONNECT BY

CONNECT BY

 

 

41.       用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 substr(name,1,25)  "Sort Area Name",

       substr(value,1,15)   "Value"

from v$sysstat

where name like 'sort%'

   

42.       使用提示(Hints)

对于表的访问,可以使用两种Hints.

FULL 和 ROWID

 

FULL hint 告诉ORACLE使用全表扫描的方式访问指定表.

例如:

   SELECT /*+ FULL(EMP) */ *

   FROM EMP

   WHERE EMPNO = 7893;

 

   ROWID hint 告诉ORACLE使用TABLE ACCESS BY ROWID的操作访问表.

 

   通常, 你需要采用TABLE ACCESS BY ROWID的方式特别是当访问大表的时候, 使用这种方式, 你需要知道ROIWD的值或者使用索引.

   如果一个大表没有被设定为缓存(CACHED)表而你希望它的数据在查询结束是仍然停留

在SGA中,你就可以使用CACHE hint 来告诉优化器把数据保留在SGA中. 通常CACHE hint 和 FULL hint 一起使用.

例如:

SELECT /*+ FULL(WORKER) CACHE(WORKER)*/ *

FROM WORK;

 

   索引hint 告诉ORACLE使用基于索引的扫描方式. 你不必说明具体的索引名称

例如:

   SELECT /*+ INDEX(LODGING) */ LODGING

   FROM LODGING

   WHERE MANAGER = ‘BILL GATES’;

  

   在不使用hint的情况下, 以上的查询应该也会使用索引,然而,如果该索引的重复值过多而你的优化器是CBO, 优化器就可能忽略索引. 在这种情况下, 你可以用INDEX hint强制ORACLE使用该索引.

 

   ORACLE hints 还包括ALL_ROWS, FIRST_ROWS, RULE,USE_NL, USE_MERGE, USE_HASH 等等.

  

译者按:

   使用hint , 表示我们对ORACLE优化器缺省的执行路径不满意,需要手工修改.

这是一个很有技巧性的工作. 我建议只针对特定的,少数的SQL进行hint的优化.

对ORACLE的优化器还是要有信心(特别是CBO)

 

时间: 2024-08-02 04:38:25

ORACLE SQL性能优化系列 (十二)的相关文章

ORACLE SQL性能优化系列 (十四) 完结篇

oracle|性能|优化 46.       连接多个扫描 如果你对一个列和一组有限的值进行比较, 优化器可能执行多次扫描并对结果进行合并连接. 举例:     SELECT *     FROM LODGING     WHERE MANAGER IN ('BILL GATES','KEN MULLER');       优化器可能将它转换成以下形式     SELECT *     FROM LODGING     WHERE MANAGER = 'BILL GATES'     OR MA

ORACLE SQL性能优化系列 (十)

oracle|性能|优化 31.       强制索引失效      如果两个或以上索引具有相同的等级,你可以强制命令ORACLE优化器使用其中的一个(通过它,检索出的记录数量少) .   举例:    SELECT ENAME FROM EMP WHERE EMPNO = 7935  AND DEPTNO + 0 = 10    /*DEPTNO上的索引将失效*/ AND EMP_TYPE || '' = 'A'  /*EMP_TYPE上的索引将失效*/   这是一种相当直接的提高查询效率的办

ORACLE SQL性能优化系列 (二)

oracle|性能|优化 4. 选择最有效率的表名顺序(只在基于规则的优化器中有效) ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理. 在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.当ORACLE处理多个表时, 会运用排序及合并的方式连接它们.首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二

ORACLE SQL性能优化系列 (五)

oracle|性能|优化 17.       使用表的别名(Alias) 当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误.   (译者注: Column歧义指的是由于SQL中不同的表具有相同的Column名,当SQL语句中出现这个Column时,SQL解析器无法判断这个Column的归属)   18.       用EXISTS替代IN 在许多基于基础表的查询中,为了满足一个条件,往往需要对

ORACLE SQL性能优化系列 (一)

oracle|性能|优化 1. 选用适合的ORACLE优化器      ORACLE的优化器共有3种:    a.  RULE (基于规则)   b. COST (基于成本)  c. CHOOSE (选择性)      设置缺省的优化器,可以通过对init.ora文件中OPTIMIZER_MODE参数的各种声明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS . 你当然也在SQL句级或是会话(session)级对其进行覆盖.    为了使用基于成本的优化器(CBO,

ORACLE SQL性能优化系列 (八)

oracle|性能|优化 25.       用索引提高效率   索引是表的一个概念部分,用来提高检索数据的效率. 实际上,ORACLE使用了一个复杂的自平衡B-tree结构. 通常,通过索引查询数据比全表扫描要快. 当ORACLE找出执行查询和Update语句的最佳路径时, ORACLE优化器将使用索引. 同样在联结多个表时使用索引也可以提高效率. 另一个使用索引的好处是,它提供了主键(primary key)的唯一性验证. 除了那些LONG或LONG RAW数据类型, 你可以索引几乎所有的列

ORACLE SQL性能优化系列 (九)

oracle|性能|优化 27.       基础表的选择   基础表(Driving Table)是指被最先访问的表(通常以全表扫描的方式被访问). 根据优化器的不同, SQL语句中基础表的选择是不一样的. 如果你使用的是CBO (COST BASED OPTIMIZER),优化器会检查SQL语句中的每个表的物理大小,索引的状态,然后选用花费最低的执行路径. 如果你用RBO (RULE BASED OPTIMIZER) , 并且所有的连接条件都有索引对应, 在这种情况下, 基础表就是FROM

ORACLE SQL性能优化系列 (十一)

oracle|性能|优化 36.       用UNION替换OR (适用于索引列) 通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. 注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低.    在下面的例子中, LOC_ID 和REGION上都建有索引. 高效:    SELECT LOC_ID , LOC_DESC , REGION    FROM LOCATION    W

ORACLE SQL性能优化系列 (十三)

oracle|性能|优化 43.       用WHERE替代ORDER BY ORDER BY 子句只在两种严格的条件下使用索引.   ORDER BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序. ORDER BY中所有的列必须定义为非空.   WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列.   例如:       表DEPT包含以下列:           DEPT_CODE    PK    NOT NULL         DEPT_DESC