July 2010
M T W T F S S
« Apr    
 1234
567891011
12131415161718
19202122232425
262728293031  

How Oracle implement ANSI left outer join syntax

At least, there will be two ways to handle left outer join, one is the traditional way to handle the case such as t1.x = t2.x (+), and the new way we saw in last article to handle the new ANSI syntax. So we will begin with such two execution plans.

cbo@ORCL> select * from t1 left outer join t2 on (t1.x = t2.x);

Execution Plan
----------------------------------------------------------
Plan hash value: 1823443478

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     6 |    78 |     5  (20)| 00:00:01 |
|*  1 |  HASH JOIN OUTER   |      |     6 |    78 |     5  (20)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T1   |     5 |    30 |     2   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   |     8 |    56 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("T1"."X"="T2"."X"(+))

cbo@ORCL> select * from t1 left outer join t2 on (t1.x = t2.x and t1.c = 11);

Execution Plan
----------------------------------------------------------
Plan hash value: 2394896828

----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |     5 |   225 |    12   (0)| 00:00:01 |
|   1 |  NESTED LOOPS OUTER |      |     5 |   225 |    12   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL | T1   |     5 |    30 |     2   (0)| 00:00:01 |
|   3 |   VIEW              |      |     1 |    39 |     2   (0)| 00:00:01 |
|*  4 |    TABLE ACCESS FULL| T2   |     1 |     7 |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   4 - filter("T1"."X"="T2"."X" AND "T1"."C"=11)

The output of the first sample should be like the output of

select * from t1,t2 where t1.x = t2.x(+);

For the second sample, we have no a simple corresponding  (+) expression. But from the execution plan, we can guess one possibility, the outline is an left outer join, composite of one table and one view, the view come from t2, and have predicates from t1.c:

select *
  from t1,
       (select t2.*
          from t1, t2
         where t1.x = t2.x
           and c = 11) t2
 where t1.x = t2.x(+);

and corresponding execution plan:

Execution Plan
----------------------------------------------------------
Plan hash value: 1247508653

-----------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |     5 |   225 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN OUTER     |      |     5 |   225 |     7  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL  | T1   |     5 |    30 |     2   (0)| 00:00:01 |
|   3 |   VIEW               |      |     1 |    39 |     5  (20)| 00:00:01 |
|*  4 |    HASH JOIN         |      |     1 |    13 |     5  (20)| 00:00:01 |
|*  5 |     TABLE ACCESS FULL| T1   |     1 |     6 |     2   (0)| 00:00:01 |
|   6 |     TABLE ACCESS FULL| T2   |     8 |    56 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("T1"."X"="T2"."X"(+))
   4 - access("T1"."X"="T2"."X")
   5 - filter("C"=13)

This is complicated than the sample output, what Oracle really does to this type of left outer join can be investigated through the 10053 trace, below is the transformed SQL.

SELECT T1.C                    C,
       T1.X                    X,
       T1.Y                    Y,
       lv.D_0 D,
       lv.X_1 X,
       lv.Y_2 Y
  FROM CBO.T1 T1,
       LATERAL((SELECT T2.D D_0, T2.X X_1, T2.Y Y_2
                 FROM CBO.T2 T2
                WHERE T1.X = T2.X
                  AND T1.C = 11))(+) lv

A lateral view is an inline view that contains correlation referring to other tables that precede it in the FROM clause. 

Like the way I show above, we can analyze the statement below, and translate them into the  (+) way.

select t1.*,t2.*
from t1 left outer join t2
on (t1.x=t2.x and (t2.d>23 or t2.d<23));

Another different issue is translating the statement below:

select t1.*,t2.* from t1 left outer join t2 on (t1.x=t2.x or t1.y = t2.y);

Oracle still use the Lateral View to generate the execution plan, but I failed to find an suitable (+) way to solve this problem, what I found is another way:

select *
  from t1, t2
 where t1.x = t2.x
    or t1.y = t2.y
union all
select t1.*, null, null, null
  from t1
 where not exists (select 1
          from t2
         where t2.x = t1.x
            or t1.y = t2.y);

This method is similar to the issue about “full outer join”.

SELECT T1.c, T2.d
FROM T1 FULL OUTER JOIN T2
ON T1.x = T2.y;

will be translated to

SELECT T1.c, T2.d
FROM T1, T2
WHERE T1.x = T2.y (+)
UNION ALL
SELECT NULL, T2.d
FROM T2
WHERE NOT EXISTS
(SELECT 1 FROM T1 WHERE T1.x = T2.y);

The general rule is that degrade left outer join to equi-join, and degrade full outer join to left outer join.

Reference:

The articles below would be useful to understand this topic:

OuterJoins in Oracle from http://optimizermagic.blogspot.com/2007/12/outerjoins-in-oracle.html

ANSI Outer Joins And Lateral Views from http://structureddata.org/2008/02/18/ansi-outer-joins-and-lateral-views/

What’s in a Condition? from http://www.oreillynet.com/pub/a/network/2002/10/01/whatsinacondition.html

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>