Index hint ignored for driving table of Outer Join[ID 316518.1]

 Index hint ignored for driving table of Outer Join[ID 316518.1]

 

 

Index hint ignored for driving table of Outer Join [ID 316518.1]

 修改时间 11-NOV-2010     类型 BULLETIN     状态 PUBLISHED 


Outer join will create a NULL row on the right hand side of a join for
every row (including NULL rows) on the left hand side.


Non-outer joins will eliminate the NULL rows.

(since NULL != NULL (or anything else))


In the following queries against oj_test and oj_test2 which has 2 rows (one of which is NULL), 
you would get the following results:


drop table oj_test;
dropt table oj_test2;

create table oj_test (col1 number);
create table oj_test2 (col1 number);

insert into oj_test values(1);
insert into oj_test2 values(1);
insert into oj_test values(NULL);

commit;

Query without outer join:

=========================

select nvl(a.col1,999), b.col1
from oj_test a, oj_test2 b
where a.col1=b.col1
/

NVL(A.COL1,999)       COL1
--------------- ----------
              1          1

1 row selected

Only 1 row is selected becuase the join eliminates all NULL values 

(since NULL != NULL (or anything else))

NB The "nvl(a.col1,999)" is simply there to more clearly illustrate 
that there is a NULL row returned
 

Query with outer join
=====================

NULLs are not eliminated with outer joins

select nvl(a.col1,999), b.col1
from oj_test a, oj_test2 b
where a.col1=b.col1 (+)
/

NVL(A.COL1,999)       COL1
--------------- ----------
              1          1
            999

2 rows selected

So in this query 2 rows are retrieved from oj_test a and then
the outer join provides a 'NULL' for this to be joined to.





Index useage
============

Outer join can affect the usage of indexes if the index is not 'NULL safe'

Query with outer join
=====================

If ther is an index on col1 of oj_test, then it cannot be used to 
drive the outer join query because it is not 'NULL safe'. Single column
indexes do not store NULLs so if this index was used then the outer join result 
would be missing the NULL row from oj_test.

 create index oj_test_ind1 on oj_test(col1);

select /*+ leading(a) use_nl(b) index(A) */ nvl(a.col1,999), b.col1
from oj_test a, oj_test2 b
where a.col1=b.col1 (+)
/

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=166 Card=82 Bytes=2132)
   1    0   NESTED LOOPS (OUTER) (Cost=166 Card=82 Bytes=2132)
   2    1     TABLE ACCESS (FULL) OF 'OJ_TEST' (Cost=2 Card=82 Bytes=1066)
   3    1     TABLE ACCESS (FULL) OF 'OJ_TEST2' (Cost=2 Card=1 Bytes=13)


Note that there is no Index access of OJ_TEST even though there is a hint.

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

*************************************************************************************

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

 

SQL> select /*+ leading(a) use_nl(b) index(a oj_test_ind1) */ nvl(a.col1,999), b.col1   2  from oj_test a, oj_test2 b   3  where a.col1=b.col1 (+)   4  /

NVL(A.COL1,999)       COL1 --------------- ----------               1          1             999

执行计划 ---------------------------------------------------------- Plan hash value: 2621508677

------------------------------------------------------------------------------- | Id  | Operation          | Name     | Rows  | Bytes | Cost (%CPU)| Time     | ------------------------------------------------------------------------------- |   0 | SELECT STATEMENT   |          |     2 |    10 |     7   (0)| 00:00:01 | |   1 |  NESTED LOOPS OUTER|          |     2 |    10 |     7   (0)| 00:00:01 | |   2 |   TABLE ACCESS FULL| OJ_TEST  |     2 |     4 |     3   (0)| 00:00:01 | |*  3 |   TABLE ACCESS FULL| OJ_TEST2 |     1 |     3 |     2   (0)| 00:00:01 | -------------------------------------------------------------------------------

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

   3 - filter("A"."COL1"="B"."COL1"(+))

统计信息 ----------------------------------------------------------           1  recursive calls           0  db block gets          22  consistent gets           0  physical reads           0  redo size         422  bytes sent via SQL*Net to client         377  bytes received via SQL*Net from client           2  SQL*Net roundtrips to/from client           0  sorts (memory)           0  sorts (disk)           2  rows processed

 

SQL>

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

*************************************************************************************

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

 

Query with no outer join

 

========================

 

 

In the non-outer join example, the NULLs are eliminated by the join, so it does not matter that the index is not 'NULL safe' and therefore the index can be used. select /*+ leading(a) use_nl(b) index(A) */ nvl(a.col1,999), b.col1 from oj_test a, oj_test2 b where a.col1=b.col1 / Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=190 Card=82 Bytes=2132) 1 0 NESTED LOOPS (Cost=190 Card=82 Bytes=2132) 2 1 INDEX (FULL SCAN) OF 'OJ_TEST_IND1' (NON-UNIQUE) (Cost=26 Card=82 Bytes=1066) 3 1 TABLE ACCESS (FULL) OF 'OJ_TEST2' (Cost=2 Card=1 Bytes=13)

 

from:metalink [ID 316518.1]

 

/

SQL> select /*+ leading(b) use_nl(a) index(A) */ nvl(a.col1,999), b.col1
  2  from oj_test a, oj_test2 b
  3  where a.col1=b.col1
  4  /

NVL(A.COL1,999)       COL1
--------------- ----------
              1          1


执行计划
----------------------------------------------------------
Plan hash value: 2197482950

-----------------------------------------------------------------------------------
| Id  | Operation          | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |              |     1 |     5 |     3   (0)| 00:00:01 |
|   1 |  NESTED LOOPS      |              |     1 |     5 |     3   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| OJ_TEST2     |     1 |     3 |     3   (0)| 00:00:01 |
|*  3 |   INDEX RANGE SCAN | OJ_TEST_IND1 |     1 |     2 |     0   (0)| 00:00:01 |
-----------------------------------------------------------------------------------

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

   3 - access("A"."COL1"="B"."COL1")
       filter("A"."COL1" IS NOT NULL)


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          8  consistent gets
          0  physical reads
          0  redo size
        392  bytes sent via SQL*Net to client
        377  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> select /*+ leading(a) use_nl(b) index(A) */ nvl(a.col1,999), b.col1
  2  from oj_test a, oj_test2 b
  3  where a.col1=b.col1
  4  /

NVL(A.COL1,999)       COL1
--------------- ----------
              1          1


执行计划
----------------------------------------------------------
Plan hash value: 1470321623

-----------------------------------------------------------------------------------
| Id  | Operation          | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |              |     1 |     5 |     4   (0)| 00:00:01 |
|   1 |  NESTED LOOPS      |              |     1 |     5 |     4   (0)| 00:00:01 |
|*  2 |   INDEX FULL SCAN  | OJ_TEST_IND1 |     1 |     2 |     1   (0)| 00:00:01 |
|*  3 |   TABLE ACCESS FULL| OJ_TEST2     |     1 |     3 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------------

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

   2 - filter("A"."COL1" IS NOT NULL)
   3 - filter("A"."COL1"="B"."COL1")


统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          8  consistent gets
          0  physical reads
          0  redo size
        392  bytes sent via SQL*Net to client
        377  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值