union 代替or的情况

技巧2:union 代替or的情况

当SQL语句中,or 条件上面有一个为子查询,并且子查询上的表与源表不同,这个时候就可以用union代替or或者你发现执行计划中的 filter 有 or 并且 or 后面跟上子查询

(EXISTS...)的时候就要注意,比如:

2 - filter("T"."LRR_DM"='e90e3fe4237c4af988477329c7f2059e' OR  
              "T"."KPR_DM"='e90e3fe4237c4af988477329c7f2059e' OR  EXISTS (SELECT 0 FROM "KHGL_KHYWDLXX" "Y"  WHERE "Y"."KH_ID"=:B1 AND 

"Y"."SSKHJL_DM"='e90e3fe4237c4af988477329c7f2059e'))  

当然了,当你看到operation中的filter也应该要注意这些

示例如下(请自己动手实验):

create table test1 as select * from dba_objects;
create table test2 as select * from dba_objects;
create index idx1 on test1(object_id);
create index idx2 on test1(owner);
create index idx3 on test2(object_id);
create index idx4 on test2(owner);

BEGIN
  DBMS_STATS.GATHER_TABLE_STATS(ownname          => 'SCOTT',
                                tabname          => 'TEST1',
                                estimate_percent => 100,
                                method_opt       => 'for  columns owner size 200',
                                no_invalidate    => FALSE,
                                degree           => 1,
                                cascade          => TRUE);
END;
/

BEGIN
  DBMS_STATS.GATHER_TABLE_STATS(ownname          => 'SCOTT',
                                tabname          => 'TEST2',
                                estimate_percent => 100,
                                method_opt       => 'for  columns owner size 200',
                                no_invalidate    => FALSE,
                                degree           => 1,
                                cascade          => TRUE);
END;
/

比如这个SQL:

select * from test1 where owner='SCOTT' or object_id in(select object_id from test2 where owner='SCOTT');

执行计划如下:

select * from test1 where owner='SCOTT' or object_id in(select object_id from test2 where owner='SCOTT');

1859 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 4136318878

------------------------------------------------------------------------------------------
| Id  | Operation			 | Name  | Rows  | Bytes | Cost (%CPU)| Time	 |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT		 |	 |  5493 |   520K|   296   (1)| 00:00:04 |
|*  1 |  FILTER 			 |	 |	 |	 |	      | 	 |
|   2 |   TABLE ACCESS FULL		 | TEST1 | 74533 |  7060K|   296   (1)| 00:00:04 |
|   3 |   BITMAP CONVERSION TO ROWIDS	 |	 |     1 |    19 |     2   (0)| 00:00:01 |
|   4 |    BITMAP AND			 |	 |	 |	 |	      | 	 |
|   5 |     BITMAP CONVERSION FROM ROWIDS|	 |	 |	 |	      | 	 |
|*  6 |      INDEX RANGE SCAN		 | IDX3  |  1860 |	 |     1   (0)| 00:00:01 |
|   7 |     BITMAP CONVERSION FROM ROWIDS|	 |	 |	 |	      | 	 |
|*  8 |      INDEX RANGE SCAN		 | IDX4  |  1860 |	 |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("OWNER"='SCOTT' OR  EXISTS (SELECT 0 FROM "TEST2" "TEST2" WHERE
	      "OBJECT_ID"=:B1 AND "OWNER"='SCOTT'))
   6 - access("OBJECT_ID"=:B1)
   8 - access("OWNER"='SCOTT')


Statistics
----------------------------------------------------------
	  1  recursive calls
	  0  db block gets
     475201  consistent gets
	  0  physical reads
	  0  redo size
      70860  bytes sent via SQL*Net to client
       1772  bytes received via SQL*Net from client
	125  SQL*Net roundtrips to/from client
	  0  sorts (memory)
	  0  sorts (disk)
       1859  rows processed




将SQL改写成UNION形式:

SQL> select * from test1 where owner='SCOTT' 
union
select * from test1 where object_id in(select object_id from test2 where owner='SCOTT');  2    3  

1859 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1667050602

------------------------------------------------------------------------------------------------
| Id  | Operation		       | Name  | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	       |       |  3719 |   386K|       |   502	(81)| 00:00:07 |
|   1 |  SORT UNIQUE		       |       |  3719 |   386K|   553K|   502	(81)| 00:00:07 |
|   2 |   UNION-ALL		       |       |       |       |       |	    |	       |
|   3 |    TABLE ACCESS BY INDEX ROWID | TEST1 |  1859 |   176K|       |    55	 (0)| 00:00:01 |
|*  4 |     INDEX RANGE SCAN	       | IDX2  |  1859 |       |       |     5	 (0)| 00:00:01 |
|*  5 |    HASH JOIN		       |       |  1860 |   210K|       |   352	 (1)| 00:00:05 |
|   6 |     TABLE ACCESS BY INDEX ROWID| TEST2 |  1860 | 35340 |       |    55	 (0)| 00:00:01 |
|*  7 |      INDEX RANGE SCAN	       | IDX4  |  1860 |       |       |     5	 (0)| 00:00:01 |
|   8 |     TABLE ACCESS FULL	       | TEST1 | 74533 |  7060K|       |   296	 (1)| 00:00:04 |
------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("OWNER"='SCOTT')
   5 - access("OBJECT_ID"="OBJECT_ID")
   7 - access("OWNER"='SCOTT')


Statistics
----------------------------------------------------------
	  1  recursive calls
	  0  db block gets
       1131  consistent gets
	  0  physical reads
	  0  redo size
      79068  bytes sent via SQL*Net to client
       1772  bytes received via SQL*Net from client
	125  SQL*Net roundtrips to/from client
	  1  sorts (memory)
	  0  sorts (disk)
       1859  rows processed

逻辑读从475201降到1131,性能提升非常明显。



posted @ 2014-02-25 11:29  czcb  阅读(408)  评论(0编辑  收藏  举报