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

原创 2003年09月02日 23:22:00

36.       UNION替换OR (适用于索引列)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

通常情况下, UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. 注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低.

   在下面的例子中, LOC_ID REGION上都建有索引.

高效:

   SELECT LOC_ID , LOC_DESC , REGION

   FROM LOCATION

   WHERE LOC_ID = 10

   <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />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, 那就需要返回记录最少的索引列写在最前面.

 

注意:

 

WHERE KEY1 = 10   (返回最少记录)

OR KEY2 = 20        (返回最多记录)

 

ORACLE 内部将以上转换为

WHERE KEY1 = 10 AND

((NOT KEY1 = 10) AND KEY2 = 20)       

 

译者按:

 

下面的测试数据仅供参考: (a = 1003 返回一条记录 , b = 1 返回1003条记录)

SQL> select * from unionvsor /*1st test*/

  2   where a = 1003 or b = 1;

1003 rows selected.

Execution Plan

----------------------------------------------------------

   0      SELECT STATEMENT Optimizer=CHOOSE

   1    0   CONCATENATION

   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'UNIONVSOR'

   3    2       INDEX (RANGE SCAN) OF 'UB' (NON-UNIQUE)

   4    1     TABLE ACCESS (BY INDEX ROWID) OF 'UNIONVSOR'

   5    4       INDEX (RANGE SCAN) OF 'UA' (NON-UNIQUE)

Statistics

----------------------------------------------------------

          0  recursive calls

          0  db block gets

        144  consistent gets

          0  physical reads

          0  redo size

      63749  bytes sent via SQL*Net to client

       7751  bytes received via SQL*Net from client

         68  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

       1003  rows processed

SQL> select * from unionvsor /*2nd test*/

  2  where b  = 1 or a = 1003 ;

1003 rows selected.

Execution Plan

----------------------------------------------------------

   0      SELECT STATEMENT Optimizer=CHOOSE

   1    0   CONCATENATION

   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'UNIONVSOR'

   3    2       INDEX (RANGE SCAN) OF 'UA' (NON-UNIQUE)

   4    1     TABLE ACCESS (BY INDEX ROWID) OF 'UNIONVSOR'

   5    4       INDEX (RANGE SCAN) OF 'UB' (NON-UNIQUE)

Statistics

----------------------------------------------------------

          0  recursive calls

          0  db block gets

        143  consistent gets

          0  physical reads

          0  redo size

      63749  bytes sent via SQL*Net to client

       7751  bytes received via SQL*Net from client

         68  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

       1003  rows processed

 

SQL> select * from unionvsor /*3rd test*/

  2  where a = 1003

  3  union

  4   select * from unionvsor

  5   where b = 1;

1003 rows selected.

Execution Plan

----------------------------------------------------------

   0      SELECT STATEMENT Optimizer=CHOOSE

   1    0   SORT (UNIQUE)

   2    1     UNION-ALL

   3    2       TABLE ACCESS (BY INDEX ROWID) OF 'UNIONVSOR'

   4    3         INDEX (RANGE SCAN) OF 'UA' (NON-UNIQUE)

   5    2       TABLE ACCESS (BY INDEX ROWID) OF 'UNIONVSOR'

   6    5         INDEX (RANGE SCAN) OF 'UB' (NON-UNIQUE)

Statistics

----------------------------------------------------------

          0  recursive calls

          0  db block gets

         10  consistent gets  

          0  physical reads

          0  redo size

      63735  bytes sent via SQL*Net to client

       7751  bytes received via SQL*Net from client

         68  SQL*Net roundtrips to/from client

          1  sorts (memory)

          0  sorts (disk)

       1003  rows processed

UNION的效果可以从consistent gets SQL*NET的数据交换量的减少看出

 

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

   

译者按:

这是一条简单易记的规则,但是实际的执行效果还须检验,在ORACLE8i下,两者的执行路径似乎是相同的. 

 

 

38.       避免在索引列上使用IS NULLIS 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;

 

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

24.       用EXPLAIN PLAN 分析SQL语句 EXPLAIN PLAN 是一个很好的分析SQL语句的工具,它甚至可以在不执行SQL的情况下分析语句. 通过分析,我们就可以知道ORAC...
  • hzfu007
  • hzfu007
  • 2006年09月13日 17:47
  • 715

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

36.       用UNION替换OR (适用于索引列)通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. 注意, 以上规则只针对多个索引列有...
  • cwwhy
  • cwwhy
  • 2005年06月27日 13:06
  • 790

ORACLE SQL性能优化汇总

ORACLE SQL性能优化汇总:SQL语句共享、ORACLE SQL 多表联合查询、where语句条件顺序、ORACEL多表连接查询指定表别名alias等...
  • tianwei7518
  • tianwei7518
  • 2015年03月11日 23:41
  • 1015

高级SQL优化(二) ——《12年资深DBA教你Oracle开发与优化——性能优化部分》

充分利用索引 索引的限制 1. 索引对不等号和NOT的限制   如果WHERE条件中出现!=或者 Oracle 10g起,在基于CBO的优化器模式下Oralce会进行自动优...
  • holandstone
  • holandstone
  • 2016年05月21日 23:36
  • 2010

ORACLE SQL性能优化系列

ORACLE SQL性能优化系列1. 选用适合的ORACLE优化器 ORACLE的优化器共有3种: a. RULE (基于规则) b. COST (基于成本)c. CHOOSE (选择性) 设置缺省的...
  • xianbin
  • xianbin
  • 2006年11月19日 14:55
  • 783

ORACLE SQL性能优化系列

 选择最有效率的表名顺序(只在基于规则的优化器中有效)        ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table...
  • meteorlWJ
  • meteorlWJ
  • 2008年06月16日 13:36
  • 534

ORACLE SQL性能优化No3--ORACLE SQL性能优化系列

1. 选用适合的ORACLE优化器      ORACLE的优化器共有3种:     a.  RULE (基于规则)   b. COST (基于成本)  c. CHOOSE (选择性)      设置...
  • elimago
  • elimago
  • 2007年07月02日 12:31
  • 788

Oracle查询性能优化(面试题:数据库查询优化也是常问的问题)

原则一:注意WHERE子句中的连接顺序:  ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WH...
  • hxpjava1
  • hxpjava1
  • 2017年02月21日 11:40
  • 1193

Oracle 数据库性能优化3日实战(企业培训)

课程名称一: Oracle性能优化及调整 课程时长 1天 课程深度: 高级 上机实验: 10%-30% 授课对象: Oracle开发人员、Oracle数据库管理人员,应用程序开发人员 课程描述...
  • robinson_0612
  • robinson_0612
  • 2017年04月05日 11:49
  • 2475

ORACLE SQL性能优化系列(9)

27. 基础表的选择 基础表(Driving Table)是指被最先访问的表(通常以全表扫描的方式被访问). 根据优化器的不同, SQL语句中基础表的选择是不一样的. 如果你使用的是CBO (COST...
  • netspecial
  • netspecial
  • 2006年05月09日 15:04
  • 496
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ORACLE SQL性能优化系列 (十一)
举报原因:
原因补充:

(最多只允许输入30个字)